我有一个简单的查询,如下所示:
INSERT INTO myTable (col1, col2) VALUES
(1,2),
(1,3),
(2,2)
我需要检查是否添加了重复值,但检查需要在两列中进行:如果 col1
和 col2
中存在值,那么我不想插入。如果该值仅存在于其中一列中,而不存在于两列中,那么应该进行插入..
换句话说,我们有下表:
+-------------------------+
|____col1____|___col2_____|
| 1 | 2 |
| 1 | 3 |
|______2_____|_____2______|
允许插入 (2,3)
和 (1,1)
等值,但不允许插入 (1,3)
被允许。
是否可以执行一次 WHERE NOT EXISTS
检查?我可能需要一次插入 1000 个值,并且我不确定对每个插入行执行 WHERE
检查是否有效。
编辑: 要添加到问题中 - 如果两列中都有重复值,我希望查询忽略此特定行并继续插入其他值而不是抛出错误。
最佳答案
您可能想要使用主键或跨这些列的唯一索引。之后,您可以使用 replace into
或者只是 insert ignore
:
create table myTable
(
a int,
b int,
primary key (a,b)
);
-- Variant 1
replace into myTable(a,b) values (1, 2);
-- Variant 2
insert ignore into myTable(a,b) values (1,2);
参见 Insert Ignore
和 Replace Into
使用后一种变体的优点是,如果记录已经存在,您就不会更改任何记录(因此无需重建任何索引),并且最能满足您对问题的需求。
但是,如果在插入违反唯一约束的记录时需要更新其他列,则可以使用 replace into
或insert into ... on duplicate key update
.
Replace into
将在插入新记录之前执行真正的删除,而 insert into ... on duplicate key update
将执行更新。虽然人们可能认为结果是相同的,但为什么两个操作都有一个声明,答案可以在副作用中找到:
Replace into
将在插入新记录之前删除旧记录。这会导致索引更新两次,执行删除和插入触发器(如果已定义),最重要的是,如果定义了外键约束(使用 on delete restrict
或 on delete cascade
),则约束的行为将完全相同就像您手动删除记录并稍后插入新版本一样。这意味着:要么您的操作因限制而失败,要么删除操作被级联到目标表(即删除那里的相关记录,尽管您只是更改了一些列数据)。
另一方面,当使用 on duplicate key update
时,更新触发器将被触发,更改列上的索引将被重写一次,并且如果定义了外键 on update cascade
对于要更改的列之一,也会执行此操作。
按照手册中所述回答评论中的问题:
If you use the IGNORE modifier, errors that occur while executing the INSERT statement are ignored. For example, without IGNORE, a row that duplicates an existing UNIQUE index or PRIMARY KEY value in the table causes a duplicate-key error and the statement is aborted. With IGNORE, the row is discarded and no error occurs. Ignored errors may generate warnings instead, although duplicate-key errors do not.
因此,所有违规行为都被视为警告而不是错误,从而导致插入完成。否则,插入将被部分应用(使用事务时除外)。违反 duplicate key
然而,甚至不产生这样的警告。尽管如此,所有违反任何约束的记录都不会被插入,但是 ignore
将确保插入所有有效记录(假定不存在系统故障或内存不足情况)。
关于MySQL:如果多个值不存在,则插入多个值,但需要多列检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45777310/