2016-07-22 16 views
2

Was ist der beste Weg, um die Ursache eines Fehlers innerhalb einer Transaktion in mysql gespeicherten Prozedur zurückgeben?MySQL Catching Ausnahmen in Transaktionen

Hier ist eine gespeicherte Prozedur, die ich erstellt habe. Aber ich bemerkte, dass, wenn ich einen Fehler in der Syntax beginne, sagen zum Beispiel ich vergesse, die WHERE Klausel in eine der update Anweisungen zu setzen, würde es nur die SELECT 'error', aber nicht die eigentliche Ursache, warum der Fehler aufgetreten ist.

Gibt es einen besseren Weg, um Fehler zu fangen wie in Java, wo Sie gerade auf

catch(SQLException e){ 
JOptionPane.showMessageDialog(null,e.getError()+"\n"+e.getMessage()); 
} 

ich kein Beispiel oder Best Practices schätzen würde.

CREATE DEFINER=`root`@`localhost` PROCEDURE `updateCurriculumDetails`(p_curriculumId INT, p_editedByUserId INT, p_curriculumName varchar(50), p_description VARCHAR(200), p_gradeLevelId INT, p_schoolYearId INT) 
BEGIN 

    DECLARE hasError BOOLEAN DEFAULT 0; 
    DECLARE CONTINUE HANDLER FOR sqlexception SET hasError = 1; 


    START TRANSACTION; 

     UPDATE curriculum_dt c 
      SET  c.`name`  = p_curriculumName, 
        c.description = p_description, 
        c.gradeLevelId = p_gradeLevelId 
      WHERE c.id   = p_curriculumId; 

     UPDATE curriculum_schoolyears_dt cs 
      SET  cs.schoolYearId = p_schoolYearId 
      WHERE cs.curriculumId = p_curriculumId; 

     UPDATE curriculum_hd SET editedBy_UserId = p_editedByUserId, 
     dateLastEdited = NOW() 
      WHERE curriculumId = p_curriculumId; 


    IF hasError THEN 
     ROLLBACK; 
     SELECT 'error'; 
    ELSE 
     COMMIT; 
     SELECT 'successfully updated' AS result; 

    END IF; 

END 

Vielen Dank im Voraus.

Antwort

1

Die Verwendung eines CONTINUE HANDLER ist hier völlig ungeeignet. Sie ermöglichen, dass die übrigen Abfragen nach Auftreten eines Fehlers ausgeführt werden, was bestenfalls eine Zeit- und Ressourcenverschwendung ist, da Sie Abfragen ausführen, von denen Sie wissen, dass sie zurückgesetzt werden. Stattdessen scheint so etwas wie dies wie ein besserer Plan:

DECLARE EXIT HANDLER FOR SQLEXCEPTION 
BEGIN 
    ROLLBACK; 
    RESIGNAL; 
END; 

Die beste Vorgehensweise ist jedoch nicht das Verfahren zu ermöglichen, um die Transaktion zu steuern. Wenn die aufrufende Sitzung bereits eine Transaktion enthält, wird START TRANSACTION; innerhalb der Prozedur stillschweigend und implizit festgeschrieben, wodurch der Aufrufer in der nicht beneidenswerten Position bleibt, dass er nicht zurückrollen kann und sich der Bedingung nicht bewusst ist.

+1

Danke für Ihre Antwort. Ich habe nach dem Lesen Ihrer Antwort festgestellt, dass ich nur hinzufüge und keine weiteren Anweisungen nach dem Update kommen, also wurde mir klar, dass es keinen Grund gibt, einen Continue-Handler wie das zu schreiben, was Sie gesagt haben. Kannst du den Teil erklären, wenn du sagst "... darf das Verfahren die Transaktion nicht kontrollieren"? Ist es nicht ratsam, Transaktionen in gespeicherte Prozeduren einzufügen? Außerdem habe ich diese https://dev.mysql.com/doc/refman/5.5/en/error-types.html gelesen, aber als ich "CALL mysql_errno()" getippt habe, hat es einen Fehler auf der Workbench zurückgegeben, die es nicht gibt . Irgendeine Möglichkeit, den Fehler zu drucken? Tnx. – p3ace

+0

'mysql_errno()' ist keine gespeicherte Prozedur. Es ist eine C-Funktion in der C-Client-Bibliothek (die Verwendung des Wortes "call" in der Dokumentation bedeutet, dass die Funktion aufgerufen wird, nicht "CALL" ein gespeicherter proc). Es wird verwendet, um den tatsächlich an den Client geworfenen Fehler zu holen - nicht einen, der von einem Handler gefangen wurde, also hier nicht hilfreich. Mit "RESIGNAL", wie oben gezeigt, können Sie den Fehler, den Sie gerade gefangen haben, nach dem Aufräumen erneut werfen. –

+0

Es ist keine gute Idee, die Steuerung von Transaktionen innerhalb von Prozeduren zu platzieren, aus dem genannten Grund: Wenn Sie eine solche Prozedur bereits während einer Transaktion aufrufen, wird Ihre aktuelle Transaktion automatisch festgeschrieben, und wenn der Vorgang abgeschlossen ist, befinden Sie sich nicht in Transaktion, aber Sie erkennen diese Tatsache nicht. Hoffentlich können Sie sehen, wie dies zu unerwartetem Verhalten führen könnte - gespenstische Action auf Distanz. –

Verwandte Themen