无法让 MySQL 在 INSERT 语句之前接受 NOT EXISTS

Posted

技术标签:

【中文标题】无法让 MySQL 在 INSERT 语句之前接受 NOT EXISTS【英文标题】:Can't get MySQL to accept NOT EXISTS before INSERT statement 【发布时间】:2014-05-02 23:54:35 【问题描述】:

请注意,我无法通过在表上放置UNIQUE 约束来解决此问题。这是业务逻辑:如果要放置在某列中的值为 N,我们允许重复行。对于任何其他值,我们不会。

所以在检查传入参数的值并发现它不是我们允许欺骗的值之后,我这样做:

INSERT INTO userItems
VALUES ('0AA4DC20-5038-4A24-100F4DB16C6A', '1qubydk59mo059x4w2q99c', 'like', NULL)
WHERE NOT EXISTS (SELECT * FROM userItems WHERE userID = '0AA4DC20-5038-4A24-100F4DB16C6A' AND itemID = '1qubydk59mo059x4w2q99c' AND action = 'like')

这会导致:“检查与您的 mysql 服务器版本相对应的手册,以获取在 WHERE NOT EXISTS (SELECT * FROM user... 附近使用的正确语法

使用IF NOT EXISTS 也不起作用。也试过这个:

IF NOT EXISTS (SELECT * FROM userItems WHERE userID = '0AA4DC20-5038-4A24-100F4DB16C6A' AND itemID = '1qubydk59mo059x4w2q99c' AND action = 'like')
THEN
INSERT INTO userItems VALUES ('0AA4DC20-5038-4A24-100F4DB16C6A', '1qubydk59mo059x4w2q99c', 'like', NULL)  
END IF

使用SELECT(按照建议)代替VALUES 提供值不会插入任何内容,即使在独立语句中也是如此。这个:

INSERT INTO userItems (SELECT '541C3FFB-0711-4949-AD23-538B19F598D6', '10sz61gbuo2k11938s', 'like', NULL FROM userItems)

不做任何事情(没有插入行,即使表完全为空)。

但是VALUES 可以:

INSERT INTO userItems VALUES ('541C3FFB-0711-4949-AD23-538B19F598D6', '10sz61gbuo2k11938s', 'like', NULL)

【问题讨论】:

WHERE NOT EXISTS 应该是 select 语句的一部分,它不适用于 VALUES 【参考方案1】:
INSERT  userItems 
(SELECT  
   '0AA4DC20-5038-4A24-100F4DB16C6A',
   '1qubydk59mo059x4w2q99c',
   'like',
    NULL
 FROM 
    userItems
 WHERE NOT EXISTS 
    (SELECT * 
     FROM userItems 
     WHERE userID = '0AA4DC20-5038-4A24-100F4DB16C6A' AND 
           itemID = '1qubydk59mo059x4w2q99c' AND 
           action = 'like'
    )
);

【讨论】:

谢谢,但没有骰子。这就是我最初尝试的方法,但它也会引发语法错误:“...在 'IF NOT EXISTS (SELECT * FROM user..." 附近使用正确的语法” 谢谢,但还是不行:“查看与您的 MySQL 服务器版本相对应的手册,以了解在 'WHERE NOT EXISTS (SELECT * FROM userItems WHERE user..." 附近使用的正确语法。” 谢谢,终于成功了。但在语法上是多么愚蠢的解决方法。我想知道为什么没有人能解释 IF NOT EXISTS 构造的失败。 WOOPS:毕竟行不通。插入不做任何事情。事实上,即使插入语句本身也不会做任何事情。我会用详细信息更新我的问题。 @Oscar :那么,您使用VALUES 成功了吗?【参考方案2】:

由于“大部分唯一”规则,普通表约束不起作用,INSERT 不采用WHERE 子句,并且裸流控制是不好的语法,我会将逻辑包装在一个过程中.

DROP PROCEDURE IF EXISTS createUserItem;
DELIMITER $$
CREATE PROCEDURE createUserItem (
    IN pUserID VARCHAR(35), 
    IN pItemID VARCHAR(35), 
    IN pAction VARCHAR(8), 
    IN pCol4   VARCHAR(4)
) 
BEGIN
    IF NOT EXISTS (
        SELECT 'X'
          FROM userItems 
         WHERE userID = pUserID 
           AND itemID = pItemID 
           AND action = pAction
    ) THEN
        INSERT INTO userItems ()
        VALUES (pUserID, pItemID, pAction, pCol4);
   END IF;
END
$$
DELIMITER ;

那你就用CALL

mysql> CALL createUserItem('0AA4DC20-5038-4A24-100F4DB16C6A', '1qubydk59mo059x4w2q99c', 'like', NULL);
Query OK, 1 row affected (0.03 sec)

【讨论】:

感谢您的意见。只是好奇:我假设您将第二个示例称为“裸流控制”;为什么语法不好?还有:为什么它不起作用? 这是一种不好的语法,因为它返回了一个语法错误。这是因为IF 只能在存储过程或函数上下文中使用。

以上是关于无法让 MySQL 在 INSERT 语句之前接受 NOT EXISTS的主要内容,如果未能解决你的问题,请参考以下文章

无法在准备好的 INSERT 语句中的 python mysql.connector 中使用 None (NULL) 值

无论如何,我无法在 Hibernate 中批处理 MySQL INSERT 语句

MYSQL - 在 INSERT 语句中使用函数

如何使用mysql语句向表中插入数据

如何在INSERT之前获取mysql行的ID

MySQL实战第四十讲- insert语句的锁为什么这么多?