Frage

diese Antwort habe ich gelernt, ein wenig über TRIGGERs und gespeicherte Prozeduren in MySQL, aber war fassungslos, dass, während BEFORE INSERT und BEFORE UPDATE Trigger Daten ändern, könnten sie scheinbar nicht dazu führen, das Insert / Update fehlschlagen (dh. Validierung). In diesem speziellen Fall war ich in der Lage dies durch Manipulation der Daten in einer solchen Art und Weise zu arbeiten, um zu bekommen als einen Primärschlüssel Duplikat zu verursachen, die in diesem speziellen Fall sinnvoll, aber nicht unbedingt Sinn in einem allgemeinen Sinn machen.

Ist diese Art von Funktionalität möglich in MySQL? In allen anderen RDBMS (meine Erfahrung beschränkt sich auf MySQL leider)? Vielleicht eine THROW EXCEPTION Stil Syntax?

War es hilfreich?

Lösung

Von diesem Blog-Post

  

MySQL Trigger: Wie Sie eine INSERT, UPDATE Sie abbrechen oder DELETE mit einem   auslösen? Auf EfNet des #mysql jemand   fragte:

     

Wie kann ich einen Trigger mache den Vorgang abzubrechen, wenn meine Geschäftsregel nicht?

     

In MySQL 5.0 und 5.1 müssen Sie   greifen, um einige Tricks ein machen   Auslöser fehlschlagen und eine sinnvolle liefern   Fehlermeldung. Die MySQL Stored   Verfahren FAQ sagt über Fehler   Handhabung:

     

SP 11. Do SPs haben eine „erhöhen“ Anweisung „Anwendungsfehler erhöhen“? Sorry, derzeit nicht. Die SQL-Standard SIGNAL und RESIGNAL Aussagen sind auf der TODO.

     

Vielleicht MySQL 5.2 wird SIGNAL umfassen   Erklärung, die diesen Hack machen   gerade aus MySQL gestohlen Stored   Verfahren Programmierung überflüssig. Was   ist der Hack? Sie gehen zu zwingen   MySQL zu versuchen, eine Spalte zu verwenden, die   ist nicht vorhanden. Hässlich? Ja. Macht es   Arbeit? Sicher.

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;

Andere Tipps

Hier ist die Art, wie ich es tat. Beachten Sie die SET NEW='some error';. MySQL werden Sie sagen, „Variable‚neue‘können nicht auf den Wert festgelegt werden". Fehler: Kann dieses Element nicht löscht Es gibt Aufzeichnungen in dem Verkaufstisch mit diesem Titel.“

Sie können diese Falle in Ihrem Code und dann zeigt die resultierenden Fehler:)

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 ;

Da dieser Artikel oben nach oben kommt, wenn ich für die Fehlersuche Handhabung in MySQL löst, dachte ich, ich würde etwas Wissen teilen.

Wenn ein Fehler auftritt, können Sie MySQL zwingen, ein SIGNAL , aber wenn Sie es als eine Klasse als SQLEXCEPTION nicht angeben, dann wird nichts passieren, da nicht alle SQLSTATEs schlecht betrachtet werden, und selbst dann würden Sie müssen sicherstellen, dass auf RESIGNAL , wenn Sie verschachtelte BEGIN / END-Blöcke .

Alternativ und einfacher wahrscheinlich immer noch, in Ihrem Trigger, erklären einen Exit-Handler und RESIGNAL die Ausnahme.

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

Und wenn in Ihrem Körper einen Fehler auftritt, wird es wieder mit einem Fehler bis an die Spitze und Ausfahrt geworfen werden. Dies kann auch in Stored Procedures und so weiter verwendet werden.

Das funktioniert mit etwas Version 5.5 +.

Dies wird abbrechen Ihre INSERT durch Auslösen einer Ausnahme (von 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$$

Verbrauch:

call MyRaiseError('Here error message!');

doen 'T Arbeit in Triggern (Dynamic SQL nicht in gespeicherten Funktion oder Trigger erlaubt)

Ich verwende eine sehr schmutzige Lösung:

If NEW.test=1 then CALL TEST_CANNOT_BE_SET_TO_1; end if;

Wenn Test = 1 Mysql die folgende Ausnahme ausgelöst:

VERFAHREN administratie.TEST_CANNOT_BE_SET_TO_1 existiert nicht

Nicht anspruchsvoll, aber schnell und sehr nützlich.

in MS SQL man könnte es mit richtigen Syntax funktioniert:

IF UPDATE(column_name)
BEGIN
  RAISEERROR
  ROLLBACK TRAN
  RETURN
END

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

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top