Sulla chiave duplicata non fare nulla


14

Sto inserendo nella tabella seguente usando LuaSQL con l'API PtokaX.

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;

Ora, il mio problema è che quando un utente (rappresentato da nick) tenta di inserire nuovamente la stessa richiesta, l' UNIQUEindice viene verificato e lo script restituisce un falso. Questo fa sì che il mio script non riesca e devo riavviare lo script.

C'è qualcosa che posso fare nel INSERT ... ON DUPLICATE KEYcomando in modo che non faccia nulla o almeno NON restituisca un errore in caso di DUPLICATE KEY?

Altrimenti dovrei andare per aggiornare il mio datedcampo con il nuovo DATETIMEvalore.

Risposte:


23

Tre modi. O IGNOREerrori duplicati:

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

o prova a fare un aggiornamento ridondante quando c'è un duplicato:

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

oppure verifica la presenza di duplicati prima di inserire:

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

Una differenza tra la terza via e le prime due è che quando ci sono duplicati, idnon verranno incrementati. Con INSERT IGNOREe INSERT ... ON DUPLICATE KEY, verrà incrementato automaticamente e poiché l'inserimento non verrà eseguito, si avranno lacune nei valori di id.

Vorrei anche aggiungere che i tuoi script dovrebbero sempre verificare la presenza di errori e non fallire quando ce n'è uno. Qualsiasi query o istruzione può non riuscire e restituire errori occasionalmente, per vari motivi. I trucchi sopra ti salveranno solo da un tipo di errore.


1

Le opzioni sono fantastiche, ne conosco solo una quarta. È possibile creare una procedura come segue (MySQL 5.5 o versioni successive).

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

Bene, ultimamente non ho usato MySQL, quindi non lo sapevo. Puoi aggiornare ed elaborare: cosa succede se si verificano altri errori (non duplicati di violazioni delle chiavi)? E come funziona esattamente (cosa significa 1062)? La query deve essere un singolo inserto o può funzionare con l'inserimento di più righe?
ypercubeᵀᴹ

1062 è una riga duplicata. Solo questo errore SQL attiva: SET v_dups = v_dups + 1;
maschera antigas
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.