web-dev-qa-db-fra.com

Sur la clé en double, ne rien faire

J'insère dans le tableau suivant en utilisant LuaSQL avec 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;

Maintenant, mon problème est, lorsqu'un utilisateur (représenté par nick) essaie à nouveau d'insérer la même demande, l'index UNIQUE est vérifié et le script renvoie un faux. Cela provoque l'échec de mon script et je dois redémarrer le script.

Y a-t-il quelque chose que je peux faire dans le INSERT ... ON DUPLICATE KEY commande pour qu'elle ne fasse rien ou du moins ne renvoie PAS d'erreur en cas de DUPLICATE KEY?

Sinon, je devrais aller pour mettre à jour mon champ dated avec la nouvelle valeur DATETIME.

14
hjpotter92

Trois façons. Soit IGNORE erreurs en double:

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

ou essayez de faire une mise à jour redondante en cas de doublon:

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

ou vérifiez les doublons avant d'insérer:

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

Une différence entre la 3ème manière et les deux premières est que lorsqu'il y a des doublons, le id ne sera pas incrémenté. Avec INSERT IGNORE et INSERT ... ON DUPLICATE KEY, il sera incrémenté automatiquement et puisque l'insertion ne sera pas effectuée, vous aurez des lacunes dans les valeurs de id.

Je dois également ajouter que vos scripts doivent toujours vérifier les erreurs et ne pas échouer quand il y en a. Toute requête ou instruction peut échouer et renvoyer des erreurs de temps en temps, pour diverses raisons. Les astuces ci-dessus ne vous éviteront qu'un seul type d'erreur.

23
ypercubeᵀᴹ

Les options sont super, j'en connais juste une quatrième. Vous pouvez créer une procédure comme suit (MySQL 5.5 ou supérieur).

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