假设我在一个表member_id
中有两列email
,users
。如果在下面的语句中找不到类似的数据,我正在尝试添加一个新行:
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
请说清楚。感谢。
答案 0 :(得分:1)
假设您对member_id
,email
或两者的组合有唯一约束,我相信如果记录不存在,您将更好地使用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