105

我很难形成有条件的 INSERT

我有 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 

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

4

13 回答 13

127

如果您的 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 语句。

于 2009-05-27T04:31:08.277 回答
54

当您在 (user, item) 上有唯一索引时,您还可以使用INSERT IGNOREwhich 静默忽略插入,而不是更新或插入行。

查询将如下所示:

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

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

于 2012-04-25T06:52:03.827 回答
37

你有没有尝试过这样的事情?

INSERT INTO x_table (instance, user, item)
SELECT 919191 as instance, 123 as user, 456 as item
FROM x_table
WHERE (user=123 and item=456)
HAVING COUNT(*) = 0;
于 2011-10-15T21:35:16.897 回答
10

UNIQUE(user, item),做:

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

user=123位是“无操作”,用于匹配ON DUPLICATE子句的语法,而在有重复项时实际上不做任何事情。

于 2009-05-27T04:37:40.513 回答
3

如果您不想设置唯一约束,这就像一个魅力:

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

希望能帮助到你 !

于 2014-08-29T11:23:48.333 回答
3

你想要的是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.

于 2015-03-27T18:49:13.327 回答
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
于 2009-05-27T04:00:26.117 回答
1

虽然在插入数据之前检查重复是很好的,但我建议你在列上放置一个唯一的约束/索引,这样就不会错误地插入重复的数据。

于 2009-05-27T04:03:02.893 回答
1

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

INSERT INTO x_table(instance, user, item) 
    SELECT 919191, 123, 456
        FROM dual
        WHERE 123 NOT IN (SELECT user FROM x_table)
于 2018-08-15T22:55:36.077 回答
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
于 2013-03-13T13:01:09.057 回答
0

对亚历克斯的回应稍作修改,您也可以只引用现有的列值:

Insert into x_table (instance, user, item) values (919191, 123, 456) 
  ON DUPLICATE KEY UPDATE user=user
于 2011-07-25T05:50:04.630 回答
0

我今天发现一个SELECT语句可以WHERE有条件,即使它没有FROM子句并且根本不读取任何表。

这使得使用这个结构有条件地插入一些东西变得非常容易:

SELECT ... INTO @condition;
-- or if you prefer: SET @condition = ...

INSERT INTO myTable (col1, col2) SELECT 'Value 1', 'Value 2' WHERE @condition;

在 MySQL 5.7 和 MariaDB 10.3 上对此进行了测试。

于 2020-09-28T07:55:06.990 回答
-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);

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

于 2009-05-27T03:56:41.883 回答