我正在执行INSERT INTO Foo VALUES (a, b, c, ...)
,有时 , 等之一a
不满足b
外键约束。
在这种情况下,我希望插入不会发生并且不会产生错误。
我可以在单个语句中执行此操作,还是必须单独执行IF EXISTS
?
是的,使用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 网站中找到的延迟约束的评论:
与一般的 MySQL 一样,在插入、删除或更新许多行的 SQL 语句中,InnoDB 逐行检查 UNIQUE 和 FOREIGN KEY 约束。在执行外键检查时,InnoDB 在它必须查看的子记录或父记录上设置共享行级锁。InnoDB 立即检查外键约束;检查不推迟到事务提交。根据 SQL 标准,默认行为应该是延迟检查。也就是说,仅在处理完整个 SQL 语句后才检查约束。在 InnoDB 实现延迟约束检查之前,有些事情是不可能的,例如删除使用外键引用自身的记录。
我们知道 MySQL innoDB 将来也可能会实现这个特性。
如果您可以完全控制插入的 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
在这种情况下,由于您正在对数据及其父表执行内连接,如果您的数据中的外键值在主表中没有对应的值,则不会插入任何内容。
最好的方法是使用:
INSERT INTO table (col1, col2) SELECT val1, val2 FROM table2 WHERE val3 = 123
当WHERE
部分结果为false
整个时INSERT
,不执行。同时SELECT val1, val2
可以包含任何你想要的子查询。
在您的情况下,您可能会检查WHERE
条件中是否存在外键。
有关更详细的说明,请参阅MySQL INSERT IF(自定义 if 语句)。