对重复键不执行任何操作


14

我将LuaSQL与PtokaX API插入下表中。

CREATE TABLE `requests` (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `ctg` VARCHAR(15) NOT NULL,
    `msg` VARCHAR(250) NOT NULL,
    `nick` VARCHAR(32) NOT NULL,
    `filled` ENUM('Y','N') NOT NULL DEFAULT 'N',
    `dated` DATETIME NOT NULL,
    `filldate` DATETIME NULL DEFAULT NULL,
    PRIMARY KEY (`id`),
    UNIQUE INDEX `nick_msg` (`nick`, `msg`),
    UNIQUE INDEX `ctg_msg` (`ctg`, `msg`)
)
COMMENT='Requests from users in any of the categories.'
COLLATE='utf8_general_ci'
ENGINE=MyISAM;

现在,我的问题是,当用户(由代表nick)尝试再次插入相同的请求时,将UNIQUE检查索引,并且脚本返回false。这会导致脚本失败,因此我必须重新启动脚本。

我可以在INSERT ... ON DUPLICATE KEY命令中做些什么,使它什么也不做,或者至少不返回错误(如果发生)DUPLICATE KEY

否则,我将不得不dated使用新DATETIME值来更新我的字段。

Answers:


23

三种方式。无论是IGNORE重复的错误:

INSERT IGNORE 
  ... ;                   -- without ON DUPLICATE KEY

或尝试在重复时进行冗余更新:

INSERT 
  ... 
ON DUPLICATE KEY UPDATE
  id = id ;

或在插入之前检查重复项:

INSERT INTO requests
  (id, ctg, msg, nick, filled, dated, filldate)
SELECT
  NULL, 'urgent', 'Help!', 'Hermione', 'Y', NOW(), NOW()
FROM
  dual
WHERE NOT EXISTS
      ( SELECT *  FROM requests  WHERE (nick, msg) = ('Hermione', 'Help!') )
  AND NOT EXISTS
      ( SELECT *  FROM requests  WHERE (ctg, msg) = ('urgent', 'Help!') ) ;

第三种方式与前两种方式的区别在于,如果有重复项,id则不会递增。使用INSERT IGNOREINSERT ... ON DUPLICATE KEY,它将自动递增,并且由于不会完成插入,因此的值中会有空白id

我还应该补充一点,您的脚本无论如何都应该始终检查错误,并且在出现错误时也不会失败。由于种种原因,任何查询或语句都可能失败并偶尔返回错误。上面的技巧只能使您避免一种错误。


1

选项很棒,我只知道第四个。您可以按照以下步骤创建过程(MySQL 5.5或更高版本)。

DELIMITER ;;
CREATE PRODECURE...
...necessary parameters...
BEGIN

DECLARE v_dups BIGINT;
DECLARE CONTINUE HANDLER FOR 1062 SET v_dups = v_dups + 1;

-- RUN SIMPLE INSERT, IF IT TAKES DUPLICATE KEY NOTHING HAPPENS
END;;

很好,我最近没有使用MySQL,所以我不知道。您是否可以更新和详细说明:如果发生其他(不是重复的键冲突)错误,该怎么办?以及它究竟如何工作(1062代表什么)?查询是否需要是单行插入或可以插入多行使用?
ypercubeᵀᴹ

1062是重复的行。只有此SQL错误会触发:SET v_dups = v_dups + 1;
billmask '17
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.