我正在执行INSERT INTO Foo VALUES (a, b, c, ...)
,有时其中一个a
,b
等不满足外键约束。
在这种情况下,我希望不会发生插入,也不会产生错误。
我可以在一个声明中执行此操作,还是必须单独执行IF EXISTS
?
答案 0 :(得分:6)
是的,使用ignore关键字:
INSERT IGNORE INTO `foo` (...) VALUES (...);
如果使用IGNORE关键字,则执行时会出现错误 INSERT语句被视为警告。例如,没有 IGNORE,一个复制现有UNIQUE索引或PRIMARY KEY的行 表中的值导致重复键错误,语句为 中止。使用IGNORE时,仍未插入行,但没有错误 发出的。
另一方面,如果你担心的是你在父母行之前插入孩子,你也可以禁用约束并在插入父母后启用它们:
SET FOREIGN_KEY_CHECKS=0;
-- do your inserts not caring about foreign keys
SET FOREIGN_KEY_CHECKS=1;
但这只有在您知道时才尊重数据完整性。
另外,我认为值得在mysql网站上添加关于deferring constraints的评论:
与MySQL一般,在插入,删除或删除的SQL语句中 更新许多行,InnoDB检查UNIQUE和FOREIGN KEY约束 行由行。执行外键检查时,InnoDB设置共享 它必须查看的子记录或父记录上的行级锁定。 InnoDB的 立即检查外键约束;支票不会延期 到事务提交。根据SQL标准,默认 行为应该推迟检查。也就是说,只有约束 在处理完整个SQL语句后检查。直到 InnoDB实现了延迟约束检查,有些事情将是 不可能,例如删除使用a引用自身的记录 外键。
我们知道MySQL innoDB将来也可以实现这个功能。
答案 1 :(得分:0)
如果您可以完全控制插入的SQL结构,可以尝试这样的操作:
insert into Foo (a, b, c)
select
x.a,
x.b,
x.c
from
(select
101 as a,
202 as b,
'ABC123' as c
from dual ) x
inner join other_table y
on x.b = y.pkid
在这种情况下,由于您正在对数据及其父表执行内部联接,如果数据中的外键值在主表中没有相应的值,则不会插入任何内容。
答案 2 :(得分:0)
最好的方法是使用:
INSERT INTO table (col1, col2) SELECT val1, val2 FROM table2 WHERE val3 = 123
当WHERE
部分结果为false
时,则不会执行整个INSERT
。同时SELECT val1, val2
可以包含您想要的任何子查询。
在您的情况下,您可能会检查WHERE
条件中是否存在外键。
有关详细说明,请参阅MySQL INSERT IF (custom if statements)。