0

Voici ma procédure dans SQL Server 2005Procédure reprise, même après l'erreur

PROCEDURE [dbo].[sp_ProjectBackup_Insert] 
    @prj_id bigint 
    AS 
    BEGIN 
    DECLARE @MSG varchar(200) 
    DECLARE @TranName varchar(200) 
    DECLARE @return_value int 


    -- 1. Starting the transaction 
    begin transaction @TranName 

    -- 2. Insert the records 

    SET IDENTITY_INSERT [PMS_BACKUP].[Common].[PROJECT] ON INSERT INTO [PMS_BACKUP].[Common].[PROJECT] ([PRJ_ID],[PRJ_NO1],[PRJ_NO2],[PRJ_NO3],[PRJ_DESC],[IS_TASKFORCE],[DATE_CREATED],[IS_APPROVED],[DATE_APPROVED],[IS_HANDEDOVER],[DATE_HANDEDOVER],[DATE_START],[DATE_FINISH],[YEAR_OF_ORDER],[CLIENT_DETAILS],[SCOPE_OF_WORK],[IS_PROPOSAL],[PRJ_MANAGER],[PRJ_NAME],[MANAGER_VALDEL],[MANAGER_CLIENT],[DEPT_ID],[locationid],[cut_off_date]) SELECT * FROM [pms].[Common].[PROJECT] T WHERE T.PRJ_ID = (@prj_id) SET IDENTITY_INSERT [PMS_BACKUP].[Common].[PROJECT] OFF  IF @@ERROR <> 0 GOTO HANDLE_ERROR 
     SET IDENTITY_INSERT [PMS_BACKUP].[Common].[DEPARTMENT_CAP] ON INSERT INTO [PMS_BACKUP].[Common].[DEPARTMENT_CAP] ([CAP_ID],[DEPT_ID],[PRJ_ID],[IS_CAPPED],[DATE_CAPPED],[CAPPED_BY],[CAP_APPROVED_BY],[STATUS],[UNCAPPED_BY],[DATE_UNCAPPED],[DESCRIPTION],[UNCAP_APPROVED_BY],[LOCATIONID]) SELECT * FROM [pms].[Common].[DEPARTMENT_CAP] T WHERE T.PRJ_ID = (@prj_id) SET IDENTITY_INSERT [PMS_BACKUP].[Common].[DEPARTMENT_CAP] OFF  IF @@ERROR <> 0 GOTO HANDLE_ERROR 
     INSERT INTO [PMS_BACKUP].[Common].[DOC_REG] SELECT * FROM [pms].[Common].[DOC_REG] T WHERE T.PRJ_ID = (@prj_id) IF @@ERROR <> 0 GOTO HANDLE_ERROR 



    -- 3. Commit transaction 

    COMMIT TRANSACTION @TranName; 

     return @@trancount; 

    HANDLE_ERROR: 
    rollback transaction @TranName 
    RETURN 1 
    END 

et la question est, même si la première requête d'insertion échoue, son pas arrêter le traitement et de reprendre le reste des requêtes d'insertion. La valeur de retour, je reçois est 1, mais dans la fenêtre de résultats, je peux voir le journal comme celui-ci

(0 row (s) affected) Msg 2627, niveau 14, État 1, Procédure sp_ProjectBackup_Insert, ligne 35 Violation de la contrainte PRIMARY KEY 'PK_PROJECT'. Impossible d'insérer la clé en double dans l'objet 'Common.PROJECT'. L'instruction a été interrompue.

(0 ligne (s) affecté)

(0 ligne (s) affecté)

Je pensais que le return 1 fera la sortie du code de gestion des erreurs, mais ne se produit pas. Un problème avec ma gestion des erreurs?

+0

Quel système de base de données utilisez-vous (SQL, Oracle, etc.) –

+0

SQL Server 2005. Ajouté à la question maintenant. – Antoops

Répondre

0

Vous devez gérer correctement les erreurs autour de vos instructions. Avec SQL 2005 et plus, cela signifie try/catch:

PROCEDURE [dbo].[sp_ProjectBackup_Insert] 
    @prj_id bigint 
    AS 
    BEGIN 
    DECLARE @MSG varchar(200) 
    DECLARE @TranName varchar(200) 
    DECLARE @return_value int 


    -- 1. Starting the transaction 
    BEGIN TRANSACTION @TranName 

    -- 2. Insert the records 

    BEGIN TRY 

     SET IDENTITY_INSERT [PMS_BACKUP].[Common].[PROJECT] ON INSERT INTO [PMS_BACKUP].[Common].[PROJECT] ([PRJ_ID],[PRJ_NO1],[PRJ_NO2],[PRJ_NO3],[PRJ_DESC],[IS_TASKFORCE],[DATE_CREATED],[IS_APPROVED],[DATE_APPROVED],[IS_HANDEDOVER],[DATE_HANDEDOVER],[DATE_START],[DATE_FINISH],[YEAR_OF_ORDER],[CLIENT_DETAILS],[SCOPE_OF_WORK],[IS_PROPOSAL],[PRJ_MANAGER],[PRJ_NAME],[MANAGER_VALDEL],[MANAGER_CLIENT],[DEPT_ID],[locationid],[cut_off_date]) SELECT * FROM [pms].[Common].[PROJECT] T WHERE T.PRJ_ID = (@prj_id) SET IDENTITY_INSERT [PMS_BACKUP].[Common].[PROJECT] OFF  IF @@ERROR <> 0 GOTO HANDLE_ERROR 
     SET IDENTITY_INSERT [PMS_BACKUP].[Common].[DEPARTMENT_CAP] ON INSERT INTO [PMS_BACKUP].[Common].[DEPARTMENT_CAP] ([CAP_ID],[DEPT_ID],[PRJ_ID],[IS_CAPPED],[DATE_CAPPED],[CAPPED_BY],[CAP_APPROVED_BY],[STATUS],[UNCAPPED_BY],[DATE_UNCAPPED],[DESCRIPTION],[UNCAP_APPROVED_BY],[LOCATIONID]) SELECT * FROM [pms].[Common].[DEPARTMENT_CAP] T WHERE T.PRJ_ID = (@prj_id) SET IDENTITY_INSERT [PMS_BACKUP].[Common].[DEPARTMENT_CAP] OFF  IF @@ERROR <> 0 GOTO HANDLE_ERROR 
      INSERT INTO [PMS_BACKUP].[Common].[DOC_REG] SELECT * FROM [pms].[Common].[DOC_REG] T WHERE T.PRJ_ID = (@prj_id) IF @@ERROR <> 0 GOTO HANDLE_ERROR 

     -- 3. Commit transaction 

     COMMIT TRANSACTION @TranName; 
     RETURN 0 

    END TRY 

    BEGIN CATCH 

     --HANDLE_ERROR 
     ROLLBACK TRANSACTION @TranName 
     RETURN 1 

    END CATCH 

    END 

(Assurez-vous de tester et débugger - devrait être bon, mais on ne sait jamais.)

La valeur de retour est uniquement pertinente pour Quelle que soit la procédure appelée, si elle ne vérifie pas le succès ou l'échec, vous pouvez avoir un problème.

2

Il y a tellement de choses qui ne vont pas, je ne sais pas par où commencer.

En ce qui concerne votre appel d'erreur, vous êtes en train de piéger s'il y a une erreur sur la dernière étape précédant l'erreur, pas si une erreur s'est produite jusqu'à présent. Puisque la dernière étape n'est pas l'insertion mais l'instruction set_identity_insert, il n'y a pas d'erreur à intercepter.

Maintenant, sur ce qui doit être réparé en plus de cela.

S'il s'agit d'une table de sauvegarde et qu'elle est uniquement utilisée comme table de sauvegarde, éliminez la propriété d'identité. Pas besoin de continuer à allumer et à éteindre l'insert, il suffit de réparer la table, il n'est pas écrit directement par les utilisateurs, les données proviennent d'une autre table, alors pourquoi a-t-elle besoin d'une identité?

Ensuite, l'erreur que vous avez reçue m'indique que ce que vous devez faire est d'insérer seulement les enregistrements qui n'existent pas déjà dans la table de sauvegarde et non tous les enregistrements. Vous devrez peut-être également mettre à jour les enregistrements existants. Vous devez d'abord tronquer la table avant de procéder à l'insertion si vous avez uniquement besoin de la période de données la plus récente et si la table de données copiée n'est pas trop volumineuse (vous ne souhaitez pas entrer de nouveau un million d'enregistrements 10 ont été changés).

Dans SQL Server 2005, vous avez des blocs TRY CATCH disponibles, vous devriez commencer à les utiliser à la place de goto.

Jamais, jamais, jamais utiliser SELECT * dans un insert. Ou chaque fois que le code ira à la production. Select * est une très mauvaise technique de programmation. Dans l'insertion par exemple, cela causera des problèmes lorsque la table initiale est modifiée lorsque vous définissez les colonnes à insérer mais pas celles dans la sélection.

Enfin, vous ne devez pas nommer les procédures stockées avec sp au démarrage. Le processus système commence par sp et SQL Server va chercher d'abord le proc avant de regarder les procédures utilisateur. C'est un peu de temps perdu chaque fois que vous appelez un proc. Dans l'ensemble, c'est mauvais pour le système et s'il leur arrive d'avoir un proc système avec le même nom, le vôtre ne sera jamais appelé.

+0

Très utile non seulement la solution mais les conseils pour améliorer la qualité du code !! – Antoops

Questions connexes