Précédent   Forum des professionnels en informatique > Bases de données > Oracle > PL/SQL
PL/SQL Forum d'entraide sur le PL/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 05/12/2011, 16h11   #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 Pas de table "new" dans un trigger ?

Bonjour,

Je suis plus habitué à l'écriture de triggers sous SQL Server que sous Oracle.

Je souhaite faire un trigger "global" (donc pas "for each row").

Lorsque les données inserrées correspondent à certains critères, je souhaite forcer la valeur inserrée.

Voici ce que j'ai tenté d'écrire :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 
CREATE OR REPLACE
TRIGGER WTRIG_EVL 
-------------------------------------------------------------------------------
--      Trigger : wtrig_evl
--      Fichier : ap$triggers:wtrig_evl.sql
--      Si on est en train de créer un retour marchandise (V/RET) alors 
--      l'emplacement de la livraison ne soit pas être repris. On est forcément
--      sur un emplacement vide pour remettre en stock non réservé client.
-------------------------------------------------------------------------------
--      Auteur    : S.DEVIDAL
--      Version |Date        |Auteur     |Objet
-------------------------------------------------------------------------------
--      V.1     | 2011-12-05 | S.DEVIDAL |Version initiale
-------------------------------------------------------------------------------
BEFORE INSERT ON EVL
BEGIN
   UPDATE new
   SET codemp = ' '
   WHERE codsoc = 218
   AND achvte = 'V'
   AND typeve = 'RET';
END;
Voici les erreurs que je me prends dans la tête :

Erreur(2,4): PL/SQL: SQL Statement ignored
Erreur(2,11): PL/SQL: ORA-00942: table or view does not exist

Pour le première erreur, j'ai aucune idée d'où ça vient.
Et pour la seconde, j'en déduis que "new" n'existe pas... Et ":new" me fait une erreur du même acabit.
StringBuilder est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/12/2011, 16h21   #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
En mode FOR EACH ROW, voici ce que ça donne :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 
CREATE OR REPLACE
TRIGGER WTRIG_EVL 
-------------------------------------------------------------------------------
--      Trigger : wtrig_evl
--      Fichier : ap$triggers:wtrig_evl.sql
--      Si on est en train de créer un retour marchandise (V/RET) alors 
--      l'emplacement de la livraison ne soit pas être repris. On est forcément
--      sur un emplacement vide pour remettre en stock non réservé client.
-------------------------------------------------------------------------------
--      Auteur    : S.DEVIDAL
--      Version |Date        |Auteur     |Objet
-------------------------------------------------------------------------------
--      V.1     | 2011-12-05 | s.DEVIDAL |Version initiale
-------------------------------------------------------------------------------
BEFORE INSERT ON EVL FOR EACH ROW
BEGIN
   IF (:new.codsoc = 218 AND :new.achvte = 'V' AND :new.typeve = 'RET') then
      :new.codemp := ' ';
   end IF;
END;
Mais pour des raisons de performances, je préférerais éviter de passer par un for each row.
StringBuilder est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/12/2011, 16h43   #3
Modérateur
 
Homme Fabien
Ingénieur d'études en décisionnel
Inscription : septembre 2008
Messages : 5 686
Détails du profil
Informations personnelles :
Nom : Homme Fabien
Âge : 34
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Ingénieur d'études en décisionnel
Secteur : Arts - Culture

Informations forums :
Inscription : septembre 2008
Messages : 5 686
Points : 10 434
Points : 10 434
Envoyer un message via ICQ à Waldar Envoyer un message via Skype™ à Waldar
Un trigger sans "FOR EACH ROW" est appelé une fois par requête.
Le trigger avec est appelé une fois par ligne.

Vu le besoin, seule la proposition FOR EACH ROW est valide !

Et en effet, pas de table "new" ou "inserted", Oracle travaille avec les références de colonnes :new / :old.
__________________
Email : http://scr.im/waldar
Waldar est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/12/2011, 16h53   #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
Ok.

Ben pour une fois que je voulais faire un PL ensembliste...

Pour le coup, c'est un peu pourri Oracle là... Donc on est obligé de se taper systématiquement un curseur quand on travaille avec un trigger Oracle et qu'on doit pouvoir manipuler les données modifiées ?
StringBuilder est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/12/2011, 17h03   #5
Membre Expert
 
Inscription : août 2009
Messages : 779
Détails du profil
Informations forums :
Inscription : août 2009
Messages : 779
Points : 1 098
Points : 1 098
Si vous pouvez identifer toutes vos lignes avec du SQL, pas la peine de faire du FOR EACH ROW, bien sûr, mais votre besoin semble fortement lié à chaque insertion.

Cela dit, une façon de faire encore plus simple serait que dans ce cas particulier, les valeurs soient directement les bonnes, plutôt que de les modifier a posteriori avec un trigger.
Rei Ichido est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/12/2011, 17h17   #6
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 Rei Ichido Voir le message
Si vous pouvez identifer toutes vos lignes avec du SQL, pas la peine de faire du FOR EACH ROW, bien sûr, mais votre besoin semble fortement lié à chaque insertion.
Non, je ne peux pas identifier les lignes dans la table : c'est au moment de l'insertion que je veux forcer à vide.
Ensuite, je dois permettre de mettre une valeur "à la main".
Donc en aucun cas, je peux faire mon UPDATE directement sur la table EVL.
En revanche, je voudrais pouvoir le faire sur les données inserrés.

Citation:
Envoyé par Rei Ichido Voir le message
Cela dit, une façon de faire encore plus simple serait que dans ce cas particulier, les valeurs soient directement les bonnes, plutôt que de les modifier a posteriori avec un trigger.
Je vous laisse prendre votre stylo et du beau papier à lettre, et demandez à Generix de corriger leurs PPE STKEMP et AFFEMP sur une version qui n'est plus maintenue...

AFFEMP :
Citation:
Ce paramètre permet de déterminer automatiquement les emplacements lors de la génération du bon de livraison ou de réception.
STKEMP :
Citation:
Ce paramètre permet, en fonctionnement standard, d’affecter les emplacements pour les produits

A1 = O
Affectation automatique des emplacements lors de la génération de tous les bons.

N4 = 0
Ne fonctionne qu’avec la fonction GBLVG2 (depuis la version 5.0-00)

Permet de personnaliser la gestion des lots lorsqu'un emplacement est réinitialisé.

La valeur de l’emplacement est remise à " " mais on conserve la valeur du lot.

Si toutes les lignes concernent le même lot alors on supprime toutes les lignes pour ne conserver que la ligne n°1 avec la quantité totale du poste.
Bah j'ai positionné les deux paramètres sur mes deux fonctions de retour marchandises GBLVG2, et je suis bien en 5.2. J'ai bien un message d'alerte qui me dit que chaque produit n'a pas été affecté par un emplacement, mais quand je vais voir ce qu'il en est réellement... Bah cet apôtre me les a affecté quand même sur un emplacement

Mais je te rassure, je ne m'amuse pas à écrire des triggers pour le plaisir... Moi aussi je préférerais que le progiciel fasse son boulot sans bugs...
StringBuilder est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/12/2011, 17h43   #7
Modérateur
 
Homme Fabien
Ingénieur d'études en décisionnel
Inscription : septembre 2008
Messages : 5 686
Détails du profil
Informations personnelles :
Nom : Homme Fabien
Âge : 34
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Ingénieur d'études en décisionnel
Secteur : Arts - Culture

Informations forums :
Inscription : septembre 2008
Messages : 5 686
Points : 10 434
Points : 10 434
Envoyer un message via ICQ à Waldar Envoyer un message via Skype™ à Waldar
Citation:
Envoyé par StringBuilder Voir le message
Non, je ne peux pas identifier les lignes dans la table : c'est au moment de l'insertion que je veux forcer à vide.
Une remarque, la colonne n'est pas à vide, elle vaut un espace !
D'ailleurs il n'y a pas de vide en Oracle, ils sont transposés en null :
Code :
1
2
3
4
5
6
SELECT case when '' IS NULL then 1 else 0 end AS tst
  FROM dual;
 
       TST
----------
         1
__________________
Email : http://scr.im/waldar
Waldar est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/12/2011, 18h01   #8
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 Waldar Voir le message
Une remarque, la colonne n'est pas à vide, elle vaut un espace !
D'ailleurs il n'y a pas de vide en Oracle, ils sont transposés en null :
Code :
1
2
3
4
5
6
SELECT case when '' IS NULL then 1 else 0 end AS tst
  FROM dual;
 
       TST
----------
         1
Abus de langage.

L'ERP Generix ne supporte pas les NULL (ça fait des croûtages en flammes quand il rencontre un NULL).

Donc les champs "vide" contiennent ' '

Et ce comportement d'Oracle, si je ne m'abuse est lié au type VARCHAR2 non ? Il me semble bien que VARCHAR supporte les chaines vides et/ou qu'une option permet de les prendre en charge.
StringBuilder est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/12/2011, 18h13   #9
Modérateur
 
Homme Fabien
Ingénieur d'études en décisionnel
Inscription : septembre 2008
Messages : 5 686
Détails du profil
Informations personnelles :
Nom : Homme Fabien
Âge : 34
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Ingénieur d'études en décisionnel
Secteur : Arts - Culture

Informations forums :
Inscription : septembre 2008
Messages : 5 686
Points : 10 434
Points : 10 434
Envoyer un message via ICQ à Waldar Envoyer un message via Skype™ à Waldar
Je pense que c'est quelque chose qu'ils ont développé il y a très longtemps sans faire la distinction entre vide et null et que c'est resté ainsi car très vite trop impactant.

Sur la documentation 11g, on retrouve cette citation très intéressante :
Citation:
Oracle Database currently treats a character value with a length of zero as null. However, this may not continue to be true in future releases, and Oracle recommends that you do not treat empty strings the same as nulls.
__________________
Email : http://scr.im/waldar
Waldar est actuellement connecté   Envoyer un message privé Réponse avec citation 10
Vieux 05/12/2011, 19h15   #10
Expert Confirmé Sénior
 
Homme François
Chef de projet NTIC
Inscription : janvier 2007
Messages : 5 353
Détails du profil
Informations personnelles :
Nom : Homme François
Âge : 51
Localisation : France

Informations professionnelles :
Activité : Chef de projet NTIC

Informations forums :
Inscription : janvier 2007
Messages : 5 353
Points : 9 743
Points : 9 743
Citation:
Envoyé par Waldar Voir le message
Et en effet, pas de table "new" ou "inserted", Oracle travaille avec les références de colonnes :new / :old.
Je suppose qu'il faut lire "références de lignes :new et :old" ici ?
__________________

Je ne réponds pas aux questions techniques par MP ! Le forum est là pour ça...


Une réponse vous a aidé ? utiliser le bouton

"L’ennui dans ce monde, c’est que les idiots sont sûrs d’eux et les gens sensés pleins de doutes". B. Russel
Bluedeep 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 15h33.


 
 
 
 
Partenaires

Hébergement Web