En clave duplicada no hacer nada

14

Estoy insertando en la siguiente tabla usando LuaSQL con 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;

Ahora, mi problema es que, cuando un usuario (representado por nick) intenta insertar la misma solicitud nuevamente, el UNIQUEíndice se verifica y el script devuelve un falso. Esto hace que mi script falle y tengo que reiniciar el script.

¿Hay algo que pueda hacer en el INSERT ... ON DUPLICATE KEYcomando para que no haga nada o al menos NO devuelva un error en caso de DUPLICATE KEY?

De lo contrario, tendría que ir para actualizar mi datedcampo con el nuevo DATETIMEvalor.

hjpotter92
fuente

Respuestas:

23

Tres maneras. Cualquiera de IGNORElos errores duplicados:

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

o intente hacer una actualización redundante cuando haya un duplicado:

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

o verifique si hay duplicados antes de insertar:

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 diferencia entre la tercera vía y las dos primeras es que cuando hay duplicados, idno se incrementará. Con INSERT IGNOREy INSERT ... ON DUPLICATE KEY, se incrementará automáticamente y dado que la inserción no se realizará, tendrá huecos en los valores de id.

También debo agregar que sus scripts siempre deben verificar si hay errores de todos modos y no fallar cuando hay uno. Cualquier consulta o declaración puede fallar y devolver errores ocasionalmente, por varias razones. Los trucos anteriores solo te salvarán de un tipo de error.

ypercubeᵀᴹ
fuente
1

Las opciones son geniales, solo conozco una cuarta. Puede crear un procedimiento como el siguiente (MySQL 5.5 o superior).

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;;
billmask
fuente
Bien, no he estado usando MySQL últimamente, así que no lo sabía. ¿Puede actualizar y explicar en detalle: qué sucede si ocurren otros errores (no violaciones de claves duplicadas)? ¿Y cómo funciona esto exactamente (qué significa 1062)? ¿La consulta debe ser una inserción simple o puede funcionar insertando varias filas?
ypercubeᵀᴹ
1062 es fila duplicada. Solo este error de SQL activa: SET v_dups = v_dups + 1;
máscara de