MySQL #1422 存储函数或触发器中不允许显式或隐式提交
Posted
技术标签:
【中文标题】MySQL #1422 存储函数或触发器中不允许显式或隐式提交【英文标题】:MySQL #1422 Explicit or implecit commit is not allowed in stored function or trigger 【发布时间】:2017-01-09 13:51:49 【问题描述】:我尝试将复制行从集合表自动化到专用表。 有时专用表不存在,因此我检查是否存在,如果需要,我在复制行之前创建表。 此代码包含在 MariaDB 的触发器中
从表“allwelds”中最新插入的行我想知道列ProjectName的内容,完整的行必须以ProjectName的名称插入到表中 首先我检查表的存在。 如果该表不存在(select 返回 0 ),我将使用变量“qname”的名称创建表并在其中插入完整的行。 如果表存在(select 返回 1),则在表中插入具有变量“qname”名称的行
以下代码导致以下错误:
BEGIN
DECLARE qname Varchar(24) DEFAULT "EMPTY";
DECLARE qid INT DEFAULT 0;
DECLARE table_exist INT DEFAULT 5;
SELECT id, ProjectName INTO qid, qname FROM allwelds WHERE id = (SELECT MAX(id) FROM allwelds );
SELECT count(*) into table_exist FROM information_schema.TABLES WHERE (TABLE_SCHEMA = 'ugm') AND (TABLE_NAME = qname );
CASE table_exist
WHEN 0 THEN
CREATE TABLE qname ( id int, Datum date, Tijd time, ProjectName Varchar(24), ...........etc, etc, ....................... );
INSERT INTO qname ( id, Datum, Tijd, ProjectName, , ...........etc, etc, ....................... )
SELECT id, date(timestamp), time(timestamp), , ...........etc, etc, ....................... ); FROM `allwelds` WHERE id = qid;
WHEN 1 THEN
INSERT INTO qname ( id, Datum, Tijd, ProjectName, , ...........etc, etc, ....................... )
SELECT id, date(timestamp), time(timestamp), , ...........etc, etc, ....................... ); FROM `allwelds` WHERE id = qid;
END CASE;
END
谁能帮我处理这段代码?
【问题讨论】:
创建表涉及隐式提交...您不能从触发器创建表 你的第一句话显示了实际的问题——在 SQL 中,你不检查表是否存在——你假设它确实存在。如果它不存在,您会收到一个无法通过从数据库中创建表来恢复的错误。我了解您希望尽可能减少麻烦,但动态表创建不是答案。它不可维护,它包含魔法,调试起来可能是一场噩梦。如果您只是假设该表存在,您的问题就会消失。如果没有 - 您的系统需要某种迁移脚本,该脚本将在首次运行时创建表。 【参考方案1】:还有一个问题有待发现。 qname
是动态的,但您有 INSERT INTO qname ...
,它使用“qname”作为静态表名。显而易见的解决方案是CONCAT
、PREPARE
、EXECUTE
等。但是,我们不要那样做。
不要创建大量具有相同架构的表。这几乎总是糟糕的设计和维护的噩梦,有时甚至是性能问题。
相反,在 单个 表中添加一个额外的列,用于将内容放入其中。并将qname
放在该列中。该表的复合PRIMARY KEY
的第一部分可能是qname
。
另一个问题...不要通过SELECT
和MAX(id)
发现列。相反,使用伪表OLD
(还有NEW
)。它更简单,更快。此外,它还避免了 MAX(id)
可以从不同连接中获取 id 的竞争条件!
底线:花时间研究TRIGGERs
并查看示例。
【讨论】:
感谢您提供宝贵的 cmets。我现在意识到这是一种“快速而肮脏”的工作方式。请你能在最后一条评论中解释更多。我不明白你关于伪表的说法 “在触发器主体中,OLD 和 NEW 关键字使您能够访问受触发器影响的行中的列。” -- dev.mysql.com/doc/refman/5.7/en/trigger-syntax.html阅读该页面的其余部分。以上是关于MySQL #1422 存储函数或触发器中不允许显式或隐式提交的主要内容,如果未能解决你的问题,请参考以下文章
MySQL 说:#1336 - 存储函数或触发器中不允许使用动态 SQL
day40 python MySQL 之 索引视图触发器存储过程函数
ORA-04082: 表级触发器中不允许使用 NEW 或 OLD 引用