MySQL WHERE NOT EXISTS错误

时间:2014-02-08 06:59:08

标签: mysql sql

假设我在一个表member_id中有两列emailusers。如果在下面的语句中找不到类似的数据,我正在尝试添加一个新行:

INSERT INTO users(member_id, email) 
VALUES (1,'k@live.com') 
WHERE NOT EXISTS (SELECT * FROM users WHERE member_id=1 AND email='k@live.com');

然而,它不起作用。 #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE EXISTS

请说清楚。感谢。

2 个答案:

答案 0 :(得分:1)

假设您对member_idemail或两者的组合有唯一约束,我相信如果记录不存在,您将更好地使用INSERT IGNORE。它将被插入。

INSERT IGNORE INTO users(member_id, email)
values (1, 'k@live.com');

如果没有唯一约束,请使用此technique here

INSERT INTO users(member_id, email) 
SELECT 1,'k@live.com'
  FROM dual 
  WHERE NOT EXISTS 
    (SELECT * FROM users WHERE member_id=1 AND email='k@live.com');

Dual用于虚拟选择而不是users,以便将插入的行限制为1.

答案 1 :(得分:1)

WHERE语句中不能有INSERT ... VALUES ...个子句。

避免重复的正常模式是添加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);

除了该约定之外,假设您没有唯一约束,但您只想修改单个insert语句的行为,那么您可以使用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,另一个具有前导列电子邮件。 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