2011-12-30 12 views
12

Desidero proteggere alcune righe dall'eliminazione e preferisco farlo utilizzando i trigger anziché la logica della mia applicazione. Sto usando il database MySQL.Proteggi riga da eliminazione in MySQL

Quello che mi è venuto in mente è questa:

DELIMITER $$ 

DROP TRIGGER `preserve_permissions`$$ 

USE `systemzarzadzaniareporterami`$$ 

CREATE TRIGGER `preserve_permissions` 
AFTER DELETE ON `permissions` 
FOR EACH ROW 
BEGIN 
IF old.`userLevel` = 0 AND old.`permissionCode` = 164 THEN 
    INSERT INTO `permissions` SET `userLevel`=0, `permissionCode`=164; 
END IF; 
END$$ 

DELIMITER ; 

ma mi dà un errore quando uso cancellare:

DELETE FROM `systemzarzadzaniareporterami`.`permissions` 
WHERE `userLevel` = 0 AND `permissionCode` = 164; 

Error Code: 1442. Can't update table 'permissions' in stored function/trigger because it is already used by statement which invoked this stored function/trigger. 

C'è un altro modo di fare una cosa simile?

risposta

13

Una soluzione potrebbe essere quella di creare una tabella figlio con una chiave esterna per la tabella delle autorizzazioni e aggiungere righe dipendenti che fanno riferimento alle singole righe per le quali si desidera bloccare l'eliminazione.

CREATE TABLE preserve_permissions (
    permission_id INT PRIMARY KEY, 
    FOREIGN KEY (permission_id) REFERENCES permissions (permission_id) 
); 

INSERT INTO perserve_permissions (permission_id) VALUES (1234); 

Ora non è possibile eliminare la riga dalle autorizzazioni con ID 1234, poiché violerebbe la dipendenza dalla chiave esterna.

Se si vuole davvero farlo con un trigger, invece di reinserire una riga quando qualcuno tenta di eliminarlo, basta annullare l'eliminazione. MySQL 5.5 ha la funzione SIGNAL per generare un SQLEXCEPTION in un processo o trigger memorizzato.

Se si utilizza MySQL 5.0 o 5.1, non è possibile utilizzare SIGNAL ma è possibile utilizzare un trucco che consiste nel dichiarare una variabile INT locale nel trigger e provare ad assegnare un valore stringa ad esso. Questo è un conflitto di tipo di dati, quindi genera un errore e interrompe l'operazione che ha generato il trigger. Il trucco più intelligente è quello di specificare un messaggio di errore appropriato nella stringa che si prova a inserire nell'INT, poiché quella stringa verrà riportata nell'errore! :-)

10

Creare una nuova tabella e creare una chiave esterna. Imposta la chiave esterna su delete - restrict.

CONSTRAINT FOREIGN KEY fk_restriction (restriction_col) 
table_to_restrict (restricted_id) ON DELETE RESTRICT ON UPDATE CASCADE 

Nota: Questo non è possibile essere fatto con MyISAM, BlackHole, ecc motore. Utilizzare con motori InnoDB e discendenti.