Précédent   Forum des professionnels en informatique > Bases de données > MySQL > SQL Procédural
SQL Procédural Forum d'entraide sur les triggers, les procédures stockées et les fonctions en MySQL
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 28/01/2011, 13h37   #1
Nouveau Membre du Club
 
Inscription : juillet 2005
Messages : 89
Détails du profil
Informations forums :
Inscription : juillet 2005
Messages : 89
Points : 32
Points : 32
Par défaut Trigger / appel procedure / sql dynamique / bonnes pratiques

Bonjour,

1/ Bonnes pratiques :
Pour plus de visibilité dans le code d'un TRIGGER, je déclare un bon nombre
de variables venant de la table mise à jour

Ex. :
Code :
1
2
3
4
5
6
7
8
9
10
DECLARE ROC_ID MEDIUMINT DEFAULT 0;
DECLARE ROC_IS SMALLINT DEFAULT 1;
DECLARE ROC_DS VARCHAR(8) DEFAULT '0';
DECLARE ROC_DE VARCHAR(8) DEFAULT 0;
 
 
SET ROC_ID=OLD.OC_0_ID;
SET ROC_IS=OLD.IsValidated;
SET ROC_DS=DATE_FORMAT(OLD.Date_starts, '%X%m%d');
SET ROC_DE=DATE_FORMAT(OLD.Date_ends, '%X%m%d');
Ceci est il a déconseillé par rapport aux performances de mySQL ?

2/ J'ai lu que la SQL dynamique ou l'appel d'une procédure dans un trigger
n'est pas possible

-A- ai je bien compris ?

-B- Un moyen de contourner cela ?
Je m'explique : pour le calcul d'un prix d'un article, je fais appel
à n paramètres qui selon leur valeur implique un traitement spécifique.

Je me vois mal faire un
Code :
1
2
3
IF Param1=X AND Param2=Y [etc] THEN
/*REQUETE*/
END IF;
Pour chaque jeu de valeurs des param...


Merci
__________________
Samish, rentier et futur retraité
Padawan #7896358
Samish est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/01/2011, 06h03   #2
Rédacteur/Modérateur

 
Avatar de Antoun
 
Homme Antoine Dinimant
Consultant en Business Intelligence
Inscription : octobre 2006
Messages : 5 854
Détails du profil
Informations personnelles :
Nom : Homme Antoine Dinimant
Âge : 42
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Consultant en Business Intelligence
Secteur : Conseil

Informations forums :
Inscription : octobre 2006
Messages : 5 854
Points : 9 544
Points : 9 544
1/ je ne vois absolument pas l'intérêt... sans même parler de performance, je trouve que tu perds énormément de lisibilité au lieu d'en gagner.

2/ Si mes souvenirs sont exacts, tu as le droit d'appeler une procédure dans un trigger, du moment que la procédure ne fait rien qui soit interdit au trigger... Plus généralement, même si tu appelais une procédure, je ne vois pas ce que tu pourrais en faire, car les procédures MySQL ne sont pas censées renvoyer de résultat.

Dans ton cas, une fonction me semblerait plus adaptée.
__________________
Antoun
Expert SQL, BO, Essbase

La bible d'Essbase est parue !
Antoun est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/01/2011, 11h21   #3
Nouveau Membre du Club
 
Inscription : juillet 2005
Messages : 89
Détails du profil
Informations forums :
Inscription : juillet 2005
Messages : 89
Points : 32
Points : 32
Bonjour Antoun

Merci de vos réponses

1/ Exact à l'usage c'est vraiment pas utile.

2/ "Dans ton cas, une fonction me semblerait plus adaptée."
Vous voulez dire :
A- appeler la func dans le trigger
B- remplacer le trigger par une func ?

Mon pb au sein de ce trigger étant de crée dynamiquement
une phrase sql excutée au sein de ce trigger

Code :
1
2
3
4
Ex.,  du style :
IF OLD.Level1_id>0 Then
SQL_clause=CONCAT(' AND Level1_id=', OLD.Level1_id);
END IF;
Merci
__________________
Samish, rentier et futur retraité
Padawan #7896358
Samish est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/01/2011, 13h22   #4
Rédacteur/Modérateur

 
Avatar de Antoun
 
Homme Antoine Dinimant
Consultant en Business Intelligence
Inscription : octobre 2006
Messages : 5 854
Détails du profil
Informations personnelles :
Nom : Homme Antoine Dinimant
Âge : 42
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Consultant en Business Intelligence
Secteur : Conseil

Informations forums :
Inscription : octobre 2006
Messages : 5 854
Points : 9 544
Points : 9 544
Je pensais à une fonction dans un trigger, avec tous les if et autres dans la fonction (qui peut ainsi être appelée par plusieurs triggers, par exemple à la fois le ON INSERT et le ON UPDATE).

Quant à ton idée d'utiliser du SQL dynamique (PREPARE / EXECUTE), je ne suis pas sûr que ce soit possible, et ce n'est pas une good practice quand ça peut être évité... si tu nous donnes la liste des cas que tu veux traiter, on peut t'aider à réécrire tout ça en SQL statique.
__________________
Antoun
Expert SQL, BO, Essbase

La bible d'Essbase est parue !
Antoun est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/02/2011, 08h59   #5
Nouveau Membre du Club
 
Inscription : juillet 2005
Messages : 89
Détails du profil
Informations forums :
Inscription : juillet 2005
Messages : 89
Points : 32
Points : 32
Bonjour,

0/ Merci de votre aide

1/ Concernant le traitement des paramètres d'insertion des prix dans le trigger, c'est ok.
J'ai fait :

Code :
1
2
3
4
5
6
7
8
9
IF OLD.Level1_ID>0 AND OLD.Level2_ID=0 AND OLD.LEVEL3_ID=0 THEN
/*INSERT ... WHERE Level1_ID=OLD.Level1_id*/
ELSEIF OLD.Level1_ID>0 AND OLD.Level2_ID>0 AND OLD.LEVEL3_ID=0 THEN
/*INSERT ... WHERE Level2_ID=OLD.Level2_id*/
ELSEIF OLD.Level1_ID>0 AND OLD.Level2_ID>0 AND OLD.LEVEL3_ID>0 THEN
/*INSERT ... WHERE Level3_ID=OLD.Level3_id*/
ELSE
/*RIEN*/
END IF;
Puis pour le paramètre marque :

Code :
1
2
3
IF OLD.Brand_id>0 THEN
/*DELETE ... WHERE OC_ID=OLD.OC_ID AND Brand_id<>OLD.Brand_id*/
END IF;
2/ Maintenant un autre pb se pose :
La phrase SQL qui joint la table td_items et la table td_items_prices.
Je m'explique :

Un article a un prix "normal" (public_price)
Un article peut avoir un prix "promo" (OC_ID=0, Discount_price)
Un article peut avoir n prix en fonction des oc (OC_ID>0, Discount_price)

Si je fais :
Code :
1
2
3
4
5
SELECT 
B.CODE, A.Discount_OC_ID
, A.Public_price, A.Discount_price
FROM td_items_parents_prices A INNER JOIN td_items_parents B ON A.Item_parent_ID=B.Item_parent_id
WHERE A.Level1_id=5 AND A.Item_parent_ID=33
J'obtiens :

Code,Discount_oc_id,Public_price,Discount_price
"ABC-1";"0";"260.000";"0" (prix public)
"ABC-1";"0";"260.000";"130.000" (prix promo)
"ABC-1";"117";"260.000";234.000"; (prix oc)

Il me faut donc dédoublonner en récupérant les prix par priorité croissante, s'ils existent :
Si Discount_oc_id=0 AND Discount_price>0 => Prix promo (priorité 1)
Si Discount_oc_id>0 AND Discount_price>0 => Prix oc (priorité 2)
Si Discount_oc_id=0 AND Discount_price=0 => Prix public (priorité 3)

Le GROUP BY A.Item_parent_id, me dédoublonne bien les prix, mais
ne me sort pas les prix par priorité.

Un tips, une autre façon de faire svp ?
Merci
__________________
Samish, rentier et futur retraité
Padawan #7896358
Samish est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/02/2011, 17h56   #6
Rédacteur/Modérateur

 
Avatar de Antoun
 
Homme Antoine Dinimant
Consultant en Business Intelligence
Inscription : octobre 2006
Messages : 5 854
Détails du profil
Informations personnelles :
Nom : Homme Antoine Dinimant
Âge : 42
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Consultant en Business Intelligence
Secteur : Conseil

Informations forums :
Inscription : octobre 2006
Messages : 5 854
Points : 9 544
Points : 9 544
Pour répondre déjà à ton 2/, si tes prix non-existant étaient NULL au lieu de 0, tu pourrais faire ça (je crois comprendre que l'arbitrage entre prix OC et prix promo est déjà fait) :

Code SQL :
COALESCE(Discount_Price, Public_price)

Si tu dois absolument garder tes zéros, ça donne :

Code SQL :
COALESCE(NULLIF(Discount_Price, 0), Public_price)
__________________
Antoun
Expert SQL, BO, Essbase

La bible d'Essbase est parue !
Antoun est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/02/2011, 18h04   #7
Rédacteur/Modérateur

 
Avatar de Antoun
 
Homme Antoine Dinimant
Consultant en Business Intelligence
Inscription : octobre 2006
Messages : 5 854
Détails du profil
Informations personnelles :
Nom : Homme Antoine Dinimant
Âge : 42
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Consultant en Business Intelligence
Secteur : Conseil

Informations forums :
Inscription : octobre 2006
Messages : 5 854
Points : 9 544
Points : 9 544
Pour ton 1/ maintenant, tu peux simplifier ton code en transformant les IF en WHERE dans ton INSERT :

Code :
1
2
3
4
5
INSERT INTO ...
SELECT ...
WHERE Level1_ID=OLD.Level1_id AND OLD.Level1_ID>0 AND OLD.Level2_ID=0 AND OLD.LEVEL3_ID=0
  OR Level2_ID=OLD.Level2_id AND OLD.Level1_ID>0 AND OLD.Level2_ID>0 AND OLD.LEVEL3_ID=0
  OR Level3_ID=OLD.Level3_id AND OLD.Level1_ID>0 AND OLD.Level2_ID>0 AND OLD.LEVEL3_ID>0
Au passage, je ne comprends pas vraiment ce que veut dire WHERE Level1_ID=OLD.Level1_id dans tes INSERT ? Les trois insertions ont bien lieu sur la même table ?

De même, pour ta gestion des marques, le IF peut se remplacer par un WHERE sur le DELETE :
Code :
1
2
3
 
DELETE ... 
WHERE OLD.Brand_id>0 AND OC_ID=OLD.OC_ID AND Brand_id<>OLD.Brand_id
__________________
Antoun
Expert SQL, BO, Essbase

La bible d'Essbase est parue !
Antoun est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/02/2011, 18h28   #8
Nouveau Membre du Club
 
Inscription : juillet 2005
Messages : 89
Détails du profil
Informations forums :
Inscription : juillet 2005
Messages : 89
Points : 32
Points : 32
Re,

0/ Un grand merci pour le temps consacré.

1/ Je teste cela et vous tiens au courant

2/ Même chose, je teste.

Je m'en suis sorti avec un :

Rem : Mes phrase sql sont des variables, dans le code, je
remplace /*CLAUSE*/ et /*LIMIT*/


Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
SELECT A.Item_parent_id, A.Discount_oc_id, A.Price_priority
, A.Public_price, A.Public_cashback
, A.Discount_price, A.Discount_amount, A.Discount_cashback
, B.Item_params_value1
, DateDiff(Current_timestamp,B.Item_date_created)
, A.Brand_ID, B.Brand_Designation, B.Brand_img
, A.Level1_id, B.Level1_designation_fr, B.Level1_designation_rw
, A.Level2_id, B.Level2_designation_fr, B.Level2_designation_rw
, A.Level3_id, B.Level3_designation_fr, B.Level3_designation_rw
FROM ( 
SELECT Item_parent_id, Discount_OC_ID
, Price_priority, Brand_id, Level1_id, Level2_id, Level3_id
, Public_price, Public_cashback
, Discount_price, Discount_amount, Discount_cashback
FROM td_items_parents_prices 
WHERE Price_isvalidated=2 /*CLAUSE*/ 
ORDER BY Price_priority DESC ) A
INNER JOIN td_items_parents_list1 B ON A.Item_parent_ID=B.Item_parent_ID
GROUP BY A.Item_parent_id
ORDER BY A.Price_priority DESC
/*LIMIT*/;
__________________
Samish, rentier et futur retraité
Padawan #7896358
Samish est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/03/2011, 14h56   #9
Membre confirmé
 
Inscription : novembre 2007
Messages : 134
Détails du profil
Informations forums :
Inscription : novembre 2007
Messages : 134
Points : 213
Points : 213
Par défaut Trigger <> Procédure stockée avec du sql dynamique

Bonjour,
Juste pour préciser un point lu dans le premier post, en effet Mysql refuse d'utiliser dans un trigger une procédure stockée qui utilise du sql dynamique. C'est franchement galère, peut être que cela sera possible prochainement ou peut être déjà en version 5.5
patic est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/03/2011, 21h56   #10
Rédacteur/Modérateur

 
Avatar de Antoun
 
Homme Antoine Dinimant
Consultant en Business Intelligence
Inscription : octobre 2006
Messages : 5 854
Détails du profil
Informations personnelles :
Nom : Homme Antoine Dinimant
Âge : 42
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Consultant en Business Intelligence
Secteur : Conseil

Informations forums :
Inscription : octobre 2006
Messages : 5 854
Points : 9 544
Points : 9 544
on peut considérer ça comme ?
__________________
Antoun
Expert SQL, BO, Essbase

La bible d'Essbase est parue !
Antoun est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 03h48.


 
 
 
 
Partenaires

Hébergement Web