Bei doppeltem Schlüssel nichts tun


14

Ich füge mit LuaSQL mit PtokaX API in die folgende Tabelle ein.

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;

Mein Problem ist nun, wenn ein Benutzer (dargestellt durch nick) versucht, dieselbe Anfrage erneut einzufügen, der UNIQUEIndex überprüft wird und das Skript einen Fehler zurückgibt. Dadurch schlägt mein Skript fehl und ich muss das Skript neu starten.

Gibt es etwas, was ich in dem INSERT ... ON DUPLICATE KEYBefehl tun kann, damit er nichts tut oder zumindest im Falle von KEINEM Fehler zurückgibt DUPLICATE KEY?

Andernfalls müsste ich mein datedFeld mit dem neuen DATETIMEWert aktualisieren .

Antworten:


23

Drei Wege. Entweder IGNOREdoppelte Fehler:

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

oder versuchen Sie ein redundantes Update durchzuführen, wenn es ein Duplikat gibt:

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

oder vor dem Einfügen auf Duplikate prüfen:

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!') ) ;

Ein Unterschied zwischen der 3. und der ersten beiden Methode besteht darin, dass bei Duplikaten die beiden idMethoden nicht inkrementiert werden. Mit INSERT IGNOREund INSERT ... ON DUPLICATE KEYwird es automatisch inkrementiert, und da das Einfügen nicht erfolgt, haben Sie Lücken in den Werten von id.

Ich sollte auch hinzufügen, dass Ihre Skripte sowieso immer nach Fehlern suchen und nicht scheitern sollten, wenn es einen gibt. Jede Abfrage oder Anweisung kann aus verschiedenen Gründen fehlschlagen und gelegentlich Fehler zurückgeben. Die oben genannten Tricks bewahren Sie nur vor einer Art von Fehlern.


1

Die Möglichkeiten sind großartig, ich kenne gerade eine vierte. Sie können eine Prozedur wie folgt erstellen (MySQL 5.5 oder höher).

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;;

Schön, ich habe MySQL in letzter Zeit nicht benutzt, also wusste ich das nicht. Können Sie Folgendes aktualisieren und näher erläutern: Was passiert, wenn andere (nicht doppelte Schlüsselverletzungen) Fehler auftreten? Und wie funktioniert das genau (wofür steht 1062)? Muss die Abfrage eine einzelne Einfügung sein oder funktioniert sie mit dem Einfügen mehrerer Zeilen?
ypercubeᵀᴹ

1062 ist doppelte Zeile. Nur dieser SQL-Fehler löst Folgendes aus: SET v_dups = v_dups + 1;
billmask
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.