MySQL:如果它们不存在,请插入多个值,但需要进行多列检查

时间:2017-08-20 00:03:00

标签: mysql sql-insert

我有一个简单的查询:

 INSERT INTO myTable (col1, col2) VALUES 
  (1,2),
  (1,3),
  (2,2)

我需要检查是否没有添加重复值但是检查需要在两列中进行:如果col1col2中存在值,那么我不想要插入。如果值仅存在于其中一列而不是两者中,那么插入应该通过..

换句话说,我们说我们有下表:

 +-------------------------+
 |____col1____|___col2_____|
 |      1     |     2      |
 |      1     |     3      |
 |______2_____|_____2______|

允许插入(2,3)(1,1)等值,但不允许(1,3)

是否可以一次进行WHERE NOT EXISTS检查?我可能需要一次插入1000个值,并且我不确定对每个插入行执行WHERE检查是否有效。

编辑: 要添加问题 - 如果两列之间存在重复值,我希望查询忽略此特定行并继续插入其他值而不是抛出错误。

1 个答案:

答案 0 :(得分:2)

您可能想要使用的是主键或跨这些列的唯一索引。之后,您可以使用replace intoinsert 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 IgnoreReplace Into

使用后一种变体的优势在于,如果任何记录已经存在,则不会更改任何记录(因此无需重建任何索引),并且最符合您对问题的需求。

但是,如果在插入违反唯一约束的记录时需要更新其他列,则可以使用replace intoinsert into ... on duplicate key update

Replace into将在插入新记录之前执行实际删除,而insert into ... on duplicate key update将执行更新。虽然有人可能会认为结果是相同的,那么为什么两个操作都有一个声明,答案可以在副作用中找到:

Replace into将在插入新记录之前删除旧记录。这会导致索引更新两次,删除和插入触发器执行(如果已定义),最重要的是,如果您定义了外键约束(on delete restricton delete cascade),则约束将行为与手动删除记录并稍后插入新版本的方式完全相同。这意味着:您的操作失败,因为限制已到位或删除操作已级联到目标表(即删除相关记录,尽管您刚刚更改了一些列数据)。

另一方面,当使用on duplicate key update时,更新触发器将被触发,更改列上的索引将被重写一次,如果为其中一列定义了外键on update cascade改变了,这个操作也被执行了。

如评论中所述,在评论中回答您的问题:

  

如果使用IGNORE修饰符,则会忽略执行INSERT语句时发生的错误。例如,如果没有IGNORE,则复制表中现有UNIQUE索引或PRIMARY KEY值的行会导致重复键错误,并且语句将中止。使用IGNORE,该行将被丢弃并且不会发生错误。虽然重复键错误没有,但忽略错误可能会生成警告。

因此,所有违规都被视为警告而不是错误,从而导致插入完成。否则,将部分应用插入(使用事务时除外)。但是,duplicate key的违规行为甚至不会产生这样的警告。尽管如此,所有违反任何约束条件的记录都不会被插入,但ignore将确保插入所有有效记录(假设没有系统故障或超出系统故障)记忆条件)。