INSERT ... VALUES ... 语句中不能有WHERE 子句。
避免重复的正常模式是添加 UNIQUE 约束。
如果您想避免添加任何重复的“member_id”值,并且还想避免添加任何重复的“email”值,那么
CREATE UNIQUE INDEX mytab_UX1 ON mytab (member_id);
CREATE UNIQUE INDEX mytab_UX2 ON mytab (email);
每当 INSERT 或 UPDATE 尝试创建重复值时,都会引发重复键异常(错误)。 MySQL 提供了 IGNORE 关键字,该关键字将抑制错误,并允许语句成功完成,但不会引入任何重复。
给定一个空表,第一个语句会插入一行,第二个和第三个语句不会。
INSERT IGNORE INTO mytab (member_id, email) VALUES (1,'k@live.com');
INSERT IGNORE INTO mytab (member_id, email) VALUES (2,'k@live.com');
INSERT IGNORE INTO mytab (member_id, email) VALUES (1,'aaa@bbb.com');
如果您只想将两列的组合限制为唯一,即您将允许第二和第三条语句插入一行,那么您将在两列的组合上添加一个 UNIQUE 约束,而不是上面的两个单独的唯一索引。
CREATE UNIQUE INDEX mytab_UX1 on mytab (member_id, email);
除了那个约定,假设你没有唯一约束,但你只想修改单个插入语句的行为,那么你可以使用 SELECT 语句返回你想要插入的值,然后您可以在 SELECT 中添加 WHERE 子句。
为了避免添加任何重复的 member_id 或重复的电子邮件,这样的事情可以完成:
INSERT INTO mytab (member_id, email)
SELECT s.member_id, s.email
FROM (SELECT 1 AS member_id, 'k@live.com' AS email) s
WHERE NOT EXISTS (SELECT 1 FROM mytab d WHERE d.member_id = s.member_id)
AND NOT EXISTS (SELECT 1 FROM mytab e WHERE e.email = s.email)
为了在大型表中获得最佳性能,您将需要至少两个索引,一个具有 member_id 前导列,一个具有 email 前导列。 NOT EXISTS 子查询可以利用索引快速定位“匹配”行,而不是扫描表中的每一行。)
同样,如果它只是您想要唯一的两列的组合,您将使用单个 NOT EXISTS 子查询,就像在您的原始查询中一样。
或者,您可以使用反连接模式作为 NOT EXISTS 子查询的等效项。
INSERT INTO mytab (member_id, email)
SELECT s.member_id, s.email
FROM (SELECT 2 AS member_id, 'k@live.com' AS email) s
LEFT
JOIN mytab d
ON d.member_id = s.member_id
LEFT
JOIN mytab e
ON e.email = s.email
WHERE d.member_id IS NULL
AND e.email IS NULL