5

我正在执行INSERT INTO Foo VALUES (a, b, c, ...),有时 , 等之一a不满足b外键约束。

在这种情况下,我希望插入不会发生并且不会产生错误。

我可以在单个语句中执行此操作,还是必须单独执行IF EXISTS

4

3 回答 3

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 网站中找到的延迟约束的评论:

与一般的 MySQL 一样,在插入、删除或更新许多行的 SQL 语句中,InnoDB 逐行检查 UNIQUE 和 FOREIGN KEY 约束。在执行外键检查时,InnoDB 在它必须查看的子记录或父记录上设置共享行级锁。InnoDB 立即检查外键约束;检查不推迟到事务提交。根据 SQL 标准,默认行为应该是延迟检查。也就是说,仅在处理完整个 SQL 语句后才检查约束。在 InnoDB 实现延迟约束检查之前,有些事情是不可能的,例如删除使用外键引用自身的记录。

我们知道 MySQL innoDB 将来也可能会实现这个特性。

于 2013-03-28T13:53:23.983 回答
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

在这种情况下,由于您正在对数据及其父表执行内连接,如果您的数据中的外键值在主表中没有对应的值,则不会插入任何内容。

于 2013-03-28T16:09:46.833 回答
0

最好的方法是使用:

INSERT INTO table (col1, col2) SELECT val1, val2 FROM table2 WHERE val3 = 123

WHERE部分结果为false整个时INSERT,不执行。同时SELECT val1, val2可以包含任何你想要的子查询。

在您的情况下,您可能会检查WHERE条件中是否存在外键。

有关更详细的说明,请参阅MySQL INSERT IF(自定义 if 语句)

于 2015-03-27T18:39:51.750 回答