【问题标题】:MySQL WHERE NOT EXISTS errorMySQL WHERE NOT EXISTS 错误
【发布时间】:2014-02-08 06:59:07
【问题描述】:

假设我在一张表users 中有两列member_idemail。如果以下语句未找到类似数据,我将尝试添加新行:

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

请解释一下。谢谢。

【问题讨论】:

  • 只需为email 列添加唯一约束
  • 谢谢,刚刚提醒我添加了唯一约束!

标签: mysql sql


【解决方案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。

【讨论】:

  • INSERT IGNORE 适用于表具有唯一约束的情况
  • @shola 谢谢 - 如果不是这种情况,我已经断言了这个假设并包括了一个替代方案。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2012-02-27
    • 1970-01-01
    • 2015-06-05
    • 2016-01-09
    • 1970-01-01
    • 1970-01-01
    • 2013-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多