Précédent   Forum des professionnels en informatique > Bases de données > MS SQL-Server > Développement
Développement Forum d'entraide sur le Transact-SQL, le CLR, les procédures stockées, les triggers, les requêtes SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 16/09/2011, 16h14   #1
Membre Expert
 
Homme Sylvain Devidal
Chef de projets Générix
Inscription : février 2010
Messages : 1 062
Détails du profil
Informations personnelles :
Nom : Homme Sylvain Devidal
Âge : 33
Localisation : France, Rhône (Rhône Alpes)

Informations professionnelles :
Activité : Chef de projets Générix
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : février 2010
Messages : 1 062
Points : 1 515
Points : 1 515
Par défaut Utilisation de RAISERROR

Salut,

J'ai une PS qui fait un certain nombre de traitements dans un bloc de transaction :

Code :
1
2
3
4
5
6
7
 
begin transaction;
	SELECT @pos = isnull(MAX(pos), 0) + 1 FROM evp WITH(holdlock) WHERE eve_id = @eve_id;
	INSERT INTO evp (eve_id, pos, pro_id, qty) VALUES (@eve_id, @pos, @pro_id, @qty);
	SET @new_id = SCOPE_IDENTITY();
	exec p_DoMvt @fct_id, @eve_id, @pro_id, @qty, 1;
commit;
J'ai un trigger sur la table evp qui fait un RAISERROR avec une sévérité de 11.
Je voudrais, sans devoir mettre un test à chaque ligne succeptible de planter :
- Faire un rollback de ma transaction, puisque je suis dans une transaction et qu'elle est mal passée
- Sortir de ma procédure

Je pensais qu'une erreur non récupérée par un TRY CATCH allait produire ce comportement.
Avec une sévirité de 1, le traitement continuait comme si de rien n'était.
Avec une sévérité de 11, la traitement s'interromp dans la procédure (ici le trigger) mais continue normalement dans le bloc appelant.

Je ne voudrais pas en arriver à l'extrême sévérité 25, qui stoppe la connexion SQL.

Je ne trouve pas de documentation qui décrive chaque niveau de sévirité 1 à 1.
Dois-je utiliser autrechose pour arriver à mes fins ?
StringBuilder est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/09/2011, 16h53   #2
Membre Expert
 
Homme Sylvain Devidal
Chef de projets Générix
Inscription : février 2010
Messages : 1 062
Détails du profil
Informations personnelles :
Nom : Homme Sylvain Devidal
Âge : 33
Localisation : France, Rhône (Rhône Alpes)

Informations professionnelles :
Activité : Chef de projets Générix
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : février 2010
Messages : 1 062
Points : 1 515
Points : 1 515
Est-ce que d'après vous, ce code fait ce que je cherche à faire ?

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
	begin try
		begin transaction;
		SELECT @pos = isnull(MAX(pos), 0) + 1 FROM evp WITH(holdlock) WHERE eve_id = @eve_id;
		INSERT INTO evp (eve_id, pos, pro_id, qty) VALUES (@eve_id, @pos, @pro_id, @qty);
		SET @new_id = SCOPE_IDENTITY();
		exec p_DoMvt @fct_id, @eve_id, @pro_id, @qty, 1;
		commit;
	end try
	begin catch
		rollback transaction;
		declare @err_msg varchar(4000);
		declare @err_sev int;
		SET @err_msg = ERROR_MESSAGE();
		SET @err_sev = ERROR_SEVERITY();
		RAISERROR(@err_msg, @err_sev, 1);
	end catch;
Y'a pas moyen de faire un truc moins usine à gaz???
StringBuilder est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/09/2011, 18h27   #3
Rédacteur/Modérateur

 
Avatar de SQLpro
 
Homme Frédéric BROUARD
Expert SGBDR & SQL
Inscription : mai 2002
Messages : 10 959
Détails du profil
Informations personnelles :
Nom : Homme Frédéric BROUARD
Localisation : France

Informations professionnelles :
Activité : Expert SGBDR & SQL
Secteur : Conseil

Informations forums :
Inscription : mai 2002
Messages : 10 959
Points : 17 791
Points : 17 791
Citation:
Envoyé par StringBuilder Voir le message
J'ai un trigger sur la table evp qui fait un RAISERROR avec une sévérité de 11.
Pourquoi une sévérité de 11, c'est vous qu'y l'avez mis ainsi ? En principe lea classe d'erreur à utiliser pour les message perso c'est 16.
A lire :
http://www.sommarskog.se/error-handling-I.html
paragraphe "More on Severity Levels"

Mais la solution que vous donnez est fausse car on ne sait pas si la transaction est encore ouverte dans la partie CATCH (elle peut avoir été annulée dans le trigger !)
Pour savoir quoi faire, utilisez la fonction XACT_STATE() :

Code :
1
2
3
4
5
6
7
8
9
begin catch
    IF XACT_STATE() <> 0
		rollback transaction;
		declare @err_msg varchar(4000);
		declare @err_sev int;
		SET @err_msg = ERROR_MESSAGE();
		SET @err_sev = ERROR_SEVERITY();
		RAISERROR(@err_msg, @err_sev, 1);
	end catch;
Par exemple.

A +
__________________
Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
Site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
Blog SQL, SQL Server, modélisation données : http://blog.developpez.com/sqlpro
http://www.sqlspot.com : modélisation, conseils, audit, optimisation, formation
* * * * * Enseignant CNAM PACA - ISEN Toulon - CESI Aix en Provence * * * * *
SQLpro est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/09/2011, 09h48   #4
Membre Expert
 
Homme Sylvain Devidal
Chef de projets Générix
Inscription : février 2010
Messages : 1 062
Détails du profil
Informations personnelles :
Nom : Homme Sylvain Devidal
Âge : 33
Localisation : France, Rhône (Rhône Alpes)

Informations professionnelles :
Activité : Chef de projets Générix
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : février 2010
Messages : 1 062
Points : 1 515
Points : 1 515
D'accord.

La severity 11, c'était effectivement de moi. J'ai trouvé entre temps qu'il vallait mieux mettre 16 (sans trop savoir pourquoi).
Ceci dit, cela n'a rien changé au comportement du programme.

OK pour votre solution.

En revanche, ma question reste ouverte quant à la faisabilité du comportement suivant :

Procédure A crée transaction
Procédure A modifie des lignes
Procédure A déclenche trigger B
Trigger B crée une transaction
Trigger B exécute des oppérations
Trigger B plante
"Vrai plantage".
=> Rollback implicite de trigger B
=> Arrêt immédiat de trigger B à l'endroit où l'erreur a été levée
=> Rollback implicite de procédure A
=> Arrêt immédiat de procédure A à l'endroit où l'erreur a été levée
=> (éventuellement, bouillonnement des rollback/arrêt immédiat au niveau des procédures appelantes)

En gros, je cherche à reproduire ce qui se passerait avec un RAISERROR avec une sévérité de 25, mais en conservant la connexion ouverte.

=> En gros, je cherche a reproduire la notion d'exception comme elle existe dans les langages type C/C++/C# : on plante tous les traitements jusqu'à ce qu'il y en ait un qui trappe proprement l'erreur. Joint avec la notion de transaction, cela me permettrait de proprement revenir à l'état initial de mon instruction appelante, sans avoir à gérer des bouillonnements d'erreur et des imbrications de transactions à la main à tous les niveaux.
StringBuilder est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/09/2011, 09h05   #5
Membre Expert
 
Avatar de iberserk
 
Homme Bruno IGNACE
Architecte de base de données
Inscription : novembre 2004
Messages : 1 299
Détails du profil
Informations personnelles :
Nom : Homme Bruno IGNACE
Âge : 30
Localisation : France, Gironde (Aquitaine)

Informations professionnelles :
Activité : Architecte de base de données
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : novembre 2004
Messages : 1 299
Points : 2 282
Points : 2 282
Envoyer un message via MSN à iberserk
Citation:
mieux mettre 16 (sans trop savoir pourquoi)
Parce qu'elle est faite pour çà...

Qu'appelez vous des "bouillonnements d'erreur"?
__________________
Prendre conscience, c'est transformer le voile qui recouvre la lumière en miroir.
iberserk est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/09/2011, 09h14   #6
Modérateur
 
Homme
Administrateur de base de données
Inscription : août 2007
Messages : 1 159
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 28
Localisation : Belgique

Informations professionnelles :
Activité : Administrateur de base de données
Secteur : Industrie Pharmaceutique

Informations forums :
Inscription : août 2007
Messages : 1 159
Points : 1 611
Points : 1 611
Citation:
Envoyé par StringBuilder Voir le message
Je ne trouve pas de documentation qui décrive chaque niveau de sévirité 1 à 1.
C'est decrit dans la doc SQL Server.
http://msdn.microsoft.com/en-us/library/ms164086.aspx
Ptit_Dje est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/09/2011, 10h53   #7
Membre Expert
 
Homme Sylvain Devidal
Chef de projets Générix
Inscription : février 2010
Messages : 1 062
Détails du profil
Informations personnelles :
Nom : Homme Sylvain Devidal
Âge : 33
Localisation : France, Rhône (Rhône Alpes)

Informations professionnelles :
Activité : Chef de projets Générix
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : février 2010
Messages : 1 062
Points : 1 515
Points : 1 515
Citation:
Envoyé par iberserk Voir le message
Parce qu'elle est faite pour çà...

Qu'appelez vous des "bouillonnements d'erreur"?
Lorsque mon trigger plante et retourne une erreur de sévérité 16, l'appelant (que ce soit une fonction, procédure, autre trigger ou batch) ne plante pas, il continue à tourner.

Je désire que l'instruction qui a délenché le trigger qui a planté soit en erreur elle aussi.

Et ainsi de suite : si cette instruction est dans une fonction, alors je veux que la fonction soit en erreur, et que la requête appelante soit en erreur.

=> Jusqu'à ce que j'arrive à un bloc try/catch qui gère convenablement l'erreur, ou jusqu'à ce que dans mon programme appelant.

Ainsi, si depuis mon programme j'appelle une procédure stockée, qui lance une fonction, qui délenche un trigger, qui exécute une ps qui lance une fonction, etc. etc. etc. plante, alors je veux que si je n'ai aucune gestion d'erreur, la procédure appelé par mon programme retourne l'erreur à mon programme et s'arrête là où il y a eu l'erreur.

Exactement de la même façon que se comporte un programme classique (C, ADA, VB, Java...).

En effet, je désire déporter au maximum les traitements de données dans des PS/Fonctions SQL, mais pour se faire, j'ai besoin d'avoir un minimum de mécanismes intelligents.

Ce qui m'étonne, c'est que contraitement à SQL Server, Oracle fonctionne bel et bien comme ça : dès qu'une intruction plante, l'erreur est propagée à tous les niveaux et plante tous les traitements appelant s'ils ne gèrent pas l'erreur proprement. SQL Serveur se contente de continuer les traitements appelant, sans se soucier une seconde de l'intégrité du traitement.
StringBuilder est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/09/2011, 19h08   #8
Membre chevronné
 
Avatar de alassanediakite
 
Homme Alassane Diakité
Conseil - Consultant en systèmes d'information
Inscription : août 2006
Messages : 539
Détails du profil
Informations personnelles :
Nom : Homme Alassane Diakité
Âge : 34
Localisation : Mali

Informations professionnelles :
Activité : Conseil - Consultant en systèmes d'information

Informations forums :
Inscription : août 2006
Messages : 539
Points : 604
Points : 604
Envoyer un message via Yahoo à alassanediakite
Citation:
Ainsi, si depuis mon programme j'appelle une procédure stockée, qui lance une fonction, qui délenche un trigger, qui exécute une ps qui lance une fonction, etc. etc. etc. plante, alors je veux que si je n'ai aucune gestion d'erreur, la procédure appelé par mon programme retourne l'erreur à mon programme et s'arrête là où il y a eu l'erreur.
Une fonction :
  • ne déclenche pas de trigger
  • n'exécute pas de PS
  • ne gère pas d'erreur
Citation:
Exactement de la même façon que se comporte un programme classique (C, ADA, VB, Java...).
TSQL n'est pas un langage comme C, VB ou ...
Citation:
En effet, je désire déporter au maximum les traitements de données dans des PS/Fonctions SQL, mais pour se faire, j'ai besoin d'avoir un minimum de mécanismes intelligents.
Présente le problème cas par cas et vous aurez une solution cas par cas.
Citation:
Ce qui m'étonne, c'est que contraitement à SQL Server, Oracle fonctionne bel et bien comme ça : dès qu'une intruction plante, l'erreur est propagée à tous les niveaux et plante tous les traitements appelant s'ils ne gèrent pas l'erreur proprement. SQL Serveur se contente de continuer les traitements appelant, sans se soucier une seconde de l'intégrité du traitement.
Évite les comparaison inutiles et aborde chaque produit avec sa solution aux problèmes. Sache par ailleurs que la bête (SQL server) est tellement immense que ta solution peut juste être dans un paramètre ou plus de configuration.
Vous me direz vos conclusions car je fais des recherches sur les "erreur" avec TSQL.
Merci d'avance.
__________________
Le monde est trop bien programmé pour être l’œuvre du hasard…
alassanediakite est déconnecté   Envoyer un message privé Réponse avec citation 10
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 02h07.


 
 
 
 
Partenaires

Hébergement Web