我有一个简单的查询:
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
检查是否有效。
编辑: 要添加问题 - 如果两列之间存在重复值,我希望查询忽略此特定行并继续插入其他值而不是抛出错误。
答案 0 :(得分:2)
您可能想要使用的是主键或跨这些列的唯一索引。之后,您可以使用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);
使用后一种变体的优势在于,如果任何记录已经存在,则不会更改任何记录(因此无需重建任何索引),并且最符合您对问题的需求。
但是,如果在插入违反唯一约束的记录时需要更新其他列,则可以使用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
改变了,这个操作也被执行了。
如评论中所述,在评论中回答您的问题:
如果使用IGNORE修饰符,则会忽略执行INSERT语句时发生的错误。例如,如果没有IGNORE,则复制表中现有UNIQUE索引或PRIMARY KEY值的行会导致重复键错误,并且语句将中止。使用IGNORE,该行将被丢弃并且不会发生错误。虽然重复键错误没有,但忽略错误可能会生成警告。
因此,所有违规都被视为警告而不是错误,从而导致插入完成。否则,将部分应用插入(使用事务时除外)。但是,duplicate key
的违规行为甚至不会产生这样的警告。尽管如此,所有违反任何约束条件的记录都不会被插入,但ignore
将确保插入所有有效记录(假设没有系统故障或超出系统故障)记忆条件)。