MySQL条件插入


98

我在形成条件插入时遇到困难

我有x_table的列(实例,用户,项目),实例ID是唯一的。我只想在用户已经没有给定项目的情况下插入新行。

例如,尝试插入instance = 919191 user = 123 item = 456

Insert into x_table (instance, user, item) values (919191, 123, 456) 
    ONLY IF there are no rows where user=123 and item=456 

朝正确方向的任何帮助或指导将不胜感激。

Answers:


115

如果您的DBMS对在执行插入操作时从哪个表中选择的表没有施加限制,请尝试:

INSERT INTO x_table(instance, user, item) 
    SELECT 919191, 123, 456
        FROM dual
        WHERE NOT EXISTS (SELECT * FROM x_table
                             WHERE user = 123 
                               AND item = 456)

在这里,dual是一个只有一行的表(最初在Oracle中找到,现在也在mysql中)。逻辑是SELECT语句将生成具有所需值的单行数据,但仅当尚未找到这些值时。

或者,查看MERGE语句。


1
dual在这种情况下,是否需要事先创建?还是查询为单独使用查询而创建的某种特殊的“临时”表?
itsmequinn 2012年

8
如果还没有dual,则需要创建它。 CREATE TABLE dual ( dummy CHAR(1) DEFAULT 'x' NOT NULL CHECK (dummy = 'x') PRIMARY KEY ); INSERT INTO dual VALUES('x'); REVOKE ALL ON dual FROM PUBLIC; GRANT SELECT ON dual TO PUBLIC;
乔纳森·勒夫勒

由于这是真棒知道
itsmequinn

11
请注意,在MySQL中,您实际上并不需要存在一个名为“双重”的表:它是一个特殊的表名,可用于从中选择任何内容。
Christopher Schultz

3
MySQL“尊重”“双重”的概念,但实际上并不存在。例如,如果您SELECT COUNT(*) FROM dual始终获得1,并且如果SELECT 'foo' FROM dual您始终获得foo。但是你不能SELECT * FROM dual,你不能DESCRIBE dual或类似的东西。我尚未检查,但我也不认为您可以撤消对的权限dual。因此,值得指出的是,它可以按您期望的方式工作...除非不是,否则;)
Christopher Schultz

52

INSERT IGNORE当(用户,项目)具有唯一索引时,也可以使用它默默地忽略插入,而不是更新或插入行。

查询将如下所示:

INSERT IGNORE INTO x_table(instance, user, item) VALUES (919191, 123, 456)

您可以使用添加唯一索引CREATE UNIQUE INDEX user_item ON x_table (user, item)


2
根据MySQL文档,INSERT IGNORE是REPLACE的副本... INSERT IGNORE:保留旧行。替换:保留新行。两者都对唯一键进行操作。
Paul Kenjora 2015年

有史以来最好的答案
jmojico

30

您是否尝试过类似的方法?

INSERT INTO x_table
SELECT 919191 as instance, 123 as user, 456 as item
FROM x_table
WHERE (user=123 and item=456)
HAVING COUNT(*) = 0;

哦,是的!只需一个SELECT语句即可生成一个聪明而又不错的解决方案
java acm

真好 这适用于首次尝试的postgresql,在我看来似乎无法接受这个答案。
强大的力量

10

使用UNIQUE(user, item),执行:

Insert into x_table (instance, user, item) values (919191, 123, 456) 
  ON DUPLICATE KEY UPDATE user=123

user=123位是“ no-op”,用于匹配ON DUPLICATE子句的语法,如果有重复项,则实际上不执行任何操作。


1
我无法设置“唯一”(用户,项目),因为当多个实例具有相同的用户和项目时可能会出现实例...而在执行此插入操作时则不会。
未知

2

如果您不想设置唯一约束,则可以像超级按钮一样工作:

INSERT INTO `table` (`column1`, `column2`) SELECT 'value1', 'value2' FROM `table` WHERE `column1` = 'value1' AND `column2` = 'value2' HAVING COUNT(`column1`) = 0

希望能帮助到你 !


2

你想要的是INSERT INTO table (...) SELECT ... WHERE ...。从MySQL 5.6手册

在您的情况下是:

INSERT INTO x_table (instance, user, item) SELECT 919191, 123, 456 
WHERE (SELECT COUNT(*) FROM x_table WHERE user=123 AND item=456) = 0

或者,也许因为您没有使用任何复杂的逻辑来确定是否运行,INSERT您可以仅对UNIQUE这两列的组合设置一个键,然后使用INSERT IGNORE


你回答了吗?我一直在ERROR 1064 (42000): 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...运行(运行5.6.34)
hlin117 '16

我认为你需要说from dual之前where
hlin117 '16

FROM DUAL如果未引用任何表,则默认为@ hlin117在MariaDB 中(请参阅本文档)。
雪人

1

如果您添加(x_table.user,x_table.item)唯一的约束,则使用相同的用户和项目插入另一行将失败。

例如:

mysql> create table x_table ( instance integer primary key auto_increment, user integer, item integer, unique (user, item));
Query OK, 0 rows affected (0.00 sec)

mysql> insert into x_table (user, item) values (1,2),(3,4);
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> insert into x_table (user, item) values (1,6);
Query OK, 1 row affected (0.00 sec)

mysql> insert into x_table (user, item) values (1,2);
ERROR 1062 (23000): Duplicate entry '1-2' for key 2

那是不对的。同一用户可以有多行,但一个用户项对不能有多行。
马修·弗拉申

是啊。我看错了 编辑以限制对。
NickZoic,2009年

尼斯评论...我使用的mysql_query(“插入”)运行PHP的查询和离开或死亡部分因此dosent警告我的错误使我没有做任何检查
Angel.King.47

1

尽管在插入数据之前检查重复是否好,但我还是建议您在列上放置唯一的约束/索引,以免错误插入任何重复的数据。


1

您可以使用以下解决方案来解决您的问题:

INSERT INTO x_table(instance, user, item) 
    SELECT 919191, 123, 456
        FROM dual
        WHERE 123 NOT IN (SELECT user FROM x_table)

尽管此代码可以回答问题,但提供有关如何和/或为什么解决问题的其他上下文将提高​​答案的长期价值。
Nic3500 '18

0

对Alex的响应进行了轻微修改,您也可以只引用现有的列值:

Insert into x_table (instance, user, item) values (919191, 123, 456) 
  ON DUPLICATE KEY UPDATE user=user

0

所以这个代表PostgreSQL

INSERT INTO x_table
SELECT NewRow.*
FROM (SELECT 919191 as instance, 123 as user, 456 as item) AS NewRow
LEFT JOIN x_table
ON x_table.user = NewRow.user AND x_table.item = NewRow.item
WHERE x_table.instance IS NULL

-1
Insert into x_table (instance, user, item) values (919191, 123, 456) 
    where ((select count(*) from x_table where user=123 and item=456) = 0);

语法可能因数据库而异...


2
这是为了什么?MySQL的?
Umair A.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.