Domanda

Nel ripulire questa risposta Ho imparato qualcosa su TRIGGER e sulle procedure memorizzate in MySQL, ma ne sono rimasto sbalordito, mentre PRIMA DI INSERIRE e PRIMA AGGIORNAMENTO si innesca potrebbero modificare i dati, apparentemente non potrebbero causare errori di inserimento / aggiornamento (ad es. validazione). In questo caso particolare sono stato in grado di farlo funzionare manipolando i dati in modo tale da causare un duplicato della chiave primaria, che in questo caso particolare aveva senso, ma non ha necessariamente senso in senso generale.

Questo tipo di funzionalità è possibile in MySQL? In qualsiasi altro RDBMS (la mia esperienza è limitata a MySQL purtroppo)? Forse una sintassi di stile THROW EXCEPTION ?

È stato utile?

Soluzione

Da questo post di blog

  

Trigger MySQL: come si interrompe un INSERT, UPDATE o DELETE con a   grilletto? Su EfNet & # 8217; s #mysql qualcuno   ha chiesto:

     

Come posso fare in modo che un trigger interrompa l'operazione se la mia regola aziendale fallisce?

     

In MySQL 5.0 e 5.1 è necessario   ricorrere a qualche trucco per fare un   grilletto fallito e fornire un significato   messaggio di errore. MySQL memorizzato   Domande frequenti sulla procedura dice questo sull'errore   Manipolazione:

     

SP 11. Gli SP hanno un & # 8220; rilancio & # 8221; dichiarazione a & # 8220; aumenta errori dell'applicazione & # 8221 ;? Siamo spiacenti, al momento no. Le istruzioni SIGNAL e RESIGNAL standard SQL si trovano su TODO.

     

Forse MySQL 5.2 includerà SIGNAL   dichiarazione che renderà questo hack   rubato direttamente da MySQL Stored   Procedura Programmazione obsoleta. Che cosa   è l'hack? Stai per forzare   MySQL per tentare di utilizzare una colonna che   non esiste. Brutto? Sì. Lo fa   lavoro? Certo.

CREATE TRIGGER mytabletriggerexample
BEFORE INSERT
FOR EACH ROW BEGIN
IF(NEW.important_value) < (fancy * dancy * calculation) THEN
    DECLARE dummy INT;

    SELECT Your meaningful error message goes here INTO dummy 
        FROM mytable
      WHERE mytable.id=new.id
END IF; END;

Altri suggerimenti

Ecco come l'ho fatto. Nota SET NEW = 'some error'; . MySQL ti dirà " La variabile "nuovo" non può essere impostata sul valore di "Errore: impossibile eliminare questo elemento. Ci sono record nella tabella di vendita con questo articolo. "& Quot;

Puoi intercettare questo nel tuo codice e quindi mostrare l'errore risultante :)

DELIMITER $
DROP TRIGGER IF EXISTS before_tblinventoryexceptionreasons_delete $
CREATE TRIGGER before_tblinventoryexceptionreasons_delete
BEFORE DELETE ON tblinventoryexceptionreasons
FOR EACH ROW BEGIN
  IF (SELECT COUNT(*) FROM tblinventoryexceptions WHERE tblinventoryexceptions.idtblinventoryexceptionreasons = old.idtblinventoryexceptionreasons) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory exception reasons table with this item.';
  END IF;
END$
DELIMITER ;

DELIMITER $
DROP TRIGGER IF EXISTS before_storesalesconfig_delete $
CREATE TRIGGER before_storesalesconfig_delete
BEFORE DELETE ON tblstoresalesconfig
FOR EACH ROW BEGIN
  IF (SELECT COUNT(*) FROM tblstoresales WHERE tblstoresales.idtblstoresalesconfig=old.idtblstoresalesconfig) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the sales table with this item.';
  END IF;
  IF (SELECT COUNT(*) FROM tblinventory WHERE tblinventory.idtblstoresalesconfig=old.idtblstoresalesconfig) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory table with this item.';
  END IF;
  IF (SELECT COUNT(*) FROM tblinventoryexceptions WHERE tblinventoryexceptions.idtblstoresalesconfig=old.idtblstoresalesconfig) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory exceptions table with this item.';
  END IF;
  IF (SELECT COUNT(*) FROM tblinvoicedetails WHERE tblinvoicedetails.idtblstoresalesconfig=old.idtblstoresalesconfig) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory details table with this item.';
  END IF;
END$
DELIMITER ;

DELIMITER $
DROP TRIGGER IF EXISTS before_tblinvoice_delete $
CREATE TRIGGER before_tblinvoice_delete
BEFORE DELETE ON tblinvoice
FOR EACH ROW BEGIN
  IF (SELECT COUNT(*) FROM tblinvoicedetails WHERE tblinvoicedetails.idtblinvoice = old.idtblinvoice) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory details table with this item.';
  END IF;
END$
DELIMITER ;

Dato che questo articolo arriva in cima quando cerco la gestione degli errori nei trigger di MySQL, ho pensato di condividere alcune conoscenze.

Se si verifica un errore, è possibile forzare MySQL a utilizzare un SEGNALE , ma se non lo specifichi come classe come SQLEXCEPTION, non accadrà nulla, poiché non tutti gli SQLSTATE sono considerati errati e anche allora dovresti assicurarti di RESIGNAL se hai blocchi BEGIN / END nidificati .

In alternativa, e probabilmente ancora più semplice, all'interno del trigger, dichiarare un gestore di uscita e dimettere l'eccezione.

CREATE TRIGGER `my_table_AINS` AFTER INSERT ON `my_table` FOR EACH ROW
BEGIN
    DECLARE EXIT HANDLER FOR SQLEXCEPTION
        RESIGNAL;
    DECLARE EXIT HANDLER FOR SQLWARNING
        RESIGNAL;
    DECLARE EXIT HANDLER FOR NOT FOUND
        RESIGNAL; 
    -- Do the work of the trigger.
END

E se nel tuo corpo si verifica un errore, verrà riportato in alto e uscirà con un errore. Questo può essere utilizzato anche nelle stored procedure e quant'altro.

Funziona con qualsiasi versione 5.5+.

Ciò interromperà il tuo INSERT sollevando un'eccezione (da http: // www.experts-exchange.com/Database/MySQL/Q_23788965.html )

DROP PROCEDURE IF EXISTS `MyRaiseError`$

CREATE PROCEDURE `MyRaiseError`(msg VARCHAR(62))
BEGIN
DECLARE Tmsg VARCHAR(80);
SET Tmsg = msg;
IF (CHAR_LENGTH(TRIM(Tmsg)) = 0 OR Tmsg IS NULL) THEN
SET Tmsg = 'ERROR GENERADO';
END IF;
SET Tmsg = CONCAT('@@MyError', Tmsg, '@@MyError');
SET @MyError = CONCAT('INSERT INTO', Tmsg);
PREPARE stmt FROM @MyError;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END$

Utilizzo:

call MyRaiseError('Here error message!');

Non funziona con i trigger (SQL dinamico non consentito nella funzione memorizzata o trigger)

Uso una soluzione molto sporca:

Se NEW.test = 1 allora   CALL TEST_CANNOT_BE_SET_TO_1; finisci se;

Quando test = 1 Mysql genera la seguente eccezione:

L'amministrazione PROCEDURE.TEST_CANNOT_BE_SET_TO_1 non esiste

Non sofisticato ma veloce e utile.

in MS SQL potresti farlo funzionare usando la sintassi corretta:

IF UPDATE(column_name)
BEGIN
  RAISEERROR
  ROLLBACK TRAN
  RETURN
END

http://msdn.microsoft.com/en-us/magazine /cc164047.aspx

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top