MySQL ON DUPLICATE KEY inserto in una tabella di audit o di registro
-
28-09-2019 - |
Domanda
C'è un modo per ottenere questo risultato?
INSERT IGNORE INTO some_table (one,two,three) VALUES(1,2,3)
ON DUPLICATE KEY (INSERT INTO audit_table VALUES(NOW(),'Duplicate key ignored')
Io davvero non voglio usare PHP per questo: (
Grazie!
Soluzione
Se si vuole considerare l'utilizzo di una stored procedure, è possibile utilizzare un DECLARE CONTINUE HANDLER
. Ecco un esempio:
CREATE TABLE users (
username VARCHAR(30),
first_name VARCHAR(30),
last_name VARCHAR(30),
PRIMARY KEY (username)
);
CREATE TABLE audit_table (timestamp datetime, description varchar(255));
DELIMITER $$
CREATE PROCEDURE add_user
(in_username VARCHAR(30),
in_first_name VARCHAR(30),
in_last_name VARCHAR(30))
MODIFIES SQL DATA
BEGIN
DECLARE duplicate_key INT DEFAULT 0;
BEGIN
DECLARE EXIT HANDLER FOR 1062 SET duplicate_key = 1;
INSERT INTO users (username, first_name, last_name)
VALUES (in_username, in_first_name, in_last_name);
END;
IF duplicate_key = 1 THEN
INSERT INTO audit_table VALUES(NOW(), 'Duplicate key ignored');
END IF;
END$$
DELIMITER ;
aggiungiamo alcuni dati, cercando di inserire una chiave duplicata:
CALL add_user('userA', 'Bob', 'Smith');
CALL add_user('userB', 'Paul', 'Green');
CALL add_user('userA', 'Jack', 'Brown');
Risultato:
SELECT * FROM users;
+----------+------------+-----------+
| username | first_name | last_name |
+----------+------------+-----------+
| userA | Bob | Smith |
| userB | Paul | Green |
+----------+------------+-----------+
2 rows in set (0.00 sec)
SELECT * FROM audit_table;
+---------------------+-----------------------+
| timestamp | description |
+---------------------+-----------------------+
| 2010-10-07 20:17:35 | Duplicate key ignored |
+---------------------+-----------------------+
1 row in set (0.00 sec)
Se il controllo è importante a livello di database, si consiglia di concedere le autorizzazioni EXECUTE
solo modo che gli utenti del database possono chiamare solo stored procedure.
Altri suggerimenti
ON DUPLICATE KEY viene utilizzato per aggiornare la riga, di non inserire in un'altra tabella, è necessario utilizzare due query in base ai primi del risultato.
EDIT: è possibile utilizzare un trigger troppo
Non so se questo avrebbe funzionato, ma sguardo istruzione IF per MySQL
Pseudo-codice
IF(SELECT id_key_index FROM tbl WHERE id_key_index = $index) THEN (UPDATE SECOND TBL);
ELSE
INSERT ...
END IF;