web-dev-qa-db-ja.com

重複キーでは何もしない

PtokaX APIでLuaSQLを使用して、次の表に挿入しています。

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値で更新する必要があります。

14
hjpotter92

3つの方法。 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!') ) ;

3番目の方法と最初の2つの方法の違いは、重複がある場合、idは増分されないことです。 INSERT IGNOREおよびINSERT ... ON DUPLICATE KEY、それは自動インクリメントされ、挿入は行われないため、idの値にギャップが生じます。

また、スクリプトは常にエラーを常にチェックし、エラーがある場合は失敗しないことも追加する必要があります。さまざまな理由により、クエリまたはステートメントが失敗してエラーが返されることがあります。上記のトリックは、1種類のエラーからのみあなたを救います。

23
ypercubeᵀᴹ

オプションは素晴らしいです、私はちょうど4番目のものを知っています。次のようにプロシージャを作成できます(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;;
1
billmask