IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Oracle Discussion :

Création dynamique de trigger dans une procédure stockée


Sujet :

Oracle

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 15
    Points : 11
    Points
    11
    Par défaut Création dynamique de trigger dans une procédure stockée
    Bonjours

    J'ai la table

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    CREATE TABLE matable
    (
      "CODE_POSTAL" CHAR(5 BYTE),
      "NOM" VARCHAR2(38 BYTE),
      "INSERT_DATE" DATE,
      "UPDATE_DATE" DATE
    )
    sur la quelle je veux créer un trigger dynamiquement.

    Dans un 1er temps,

    Quand je fais

    Code 1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    create or replace
    TRIGGER UPDATE_matable_TRIGGER
    BEFORE UPDATE ON matable
    FOR EACH ROW
    BEGIN
      SELECT SYSDATE INTO :new.UPDATE_DATE FROM DUAL;
    END;
    ça marche!

    Quand je fais

    Code 2
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    begin
    EXECUTE IMMEDIATE 'CREATE OR REPLACE TRIGGER UPDATE_matable_TRIGGER BEFORE UPDATE ON matable FOR EACH ROW BEGIN
      SELECT SYSDATE INTO :new.UPDATE_DATE FROM DUAL;END;';
    end;/
    ça marche!

    Mais que je met ce code dans une procédure stocké d'un package
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    PROCEDURE create_update_trigger(tableName IN VARCHAR2) IS
    BEGIN
      EXECUTE IMMEDIATE 'CREATE OR REPLACE TRIGGER UPDATE_' || tableName || '_TRIGGER BEFORE UPDATE ON ' || tableName || ' FOR EACH ROW
        BEGIN
          SELECT SYSDATE INTO :new.UPDATE_DATE FROM DUAL;
        END;';
    EXCEPTION
      WHEN OTHERS THEN RAISE;
    END create_update_trigger;
    et que je fais appel à cette procédure
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    begin
      UPDATER.create_update_trigger('matable');
    end;
    /
    on me réponds:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    01031. 00000 -  "insufficient privileges"


    Ce que je ne comprend pas c'est pourquoi.

    Car j'arrive très bien a créer un trigger sur cette table
    que ce soit avec le code 1 ou le code 2;

    Mais dès que je veux passé par une procédure stocké,
    ça ne marche plus, et ne je vois pas pourquoi le problème viendrais des droits
    Car ce sont tous des objets d'un même schéma (MON schéma)

    Quelqu'un peut-il me dire où est la faute?

  2. #2
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 388
    Points
    18 388
    Par défaut
    Pour votre problème je ne sais pas, par contre vous pouvez remplacer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT SYSDATE INTO :new.UPDATE_DATE FROM DUAL;
    Par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    :new.UPDATE_DATE := SYSDATE;
    Vous économisez les changements de contexte entre les moteurs SQL et PL/SQL, et c'est nettement plus performant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    declare
        v$_date date;
        v$_time pls_integer;
        v$_loop constant pls_integer default 1e6;
     
    begin
        -- Test 1
        v$_time := dbms_utility.get_time();
        for i in 1..v$_loop
        loop
          select sysdate into v$_date from dual;
        end loop;
        dbms_output.put_line('Temps 1 : ' || to_char(dbms_utility.get_time() - v$_time));
     
        -- Test 2
        v$_time := dbms_utility.get_time();
        for i in 1..v$_loop
        loop
           v$_date := sysdate;
        end loop;
        dbms_output.put_line('Temps 2 : ' || to_char(dbms_utility.get_time() - v$_time));
     
    end;
     
    Temps 1 : 1685
    Temps 2 : 45

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 15
    Points : 11
    Points
    11
    Par défaut
    Je note, merci pour l'astuce.
    Je la mettrais en place dès que ça fonctionnera...

  4. #4
    Rédacteur

    Homme Profil pro
    Consultant / formateur Oracle et SQL Server
    Inscrit en
    Décembre 2002
    Messages
    3 461
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Consultant / formateur Oracle et SQL Server

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 461
    Points : 8 079
    Points
    8 079
    Par défaut
    Citation Envoyé par ignis666 Voir le message
    Quelqu'un peut-il me dire où est la faute?
    Avant même de parler de syntaxe :
    - pourquoi créer un déclencheur (ou n'importe quoi d'autre) dynamiquement si ça peut être fait normalement ?
    - pourquoi créer un déclencheur alors qu'un simple attribut DEFAULT sur la colonne produira le même résultat ?
    - et pourquoi mettre vos noms de colonnes entre guillemets, ce qui ne vous apporte aucun avantage, mais des inconvénients ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    CREATE TABLE matable ( 
    CODE_POSTAL CHAR(5 BYTE), 
    NOM VARCHAR2(38 BYTE), 
    INSERT_DATE DATE, 
    UPDATE_DATE DATE DEFAULT SYSDATE );

  5. #5
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Mars 2010
    Messages
    536
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 536
    Points : 1 359
    Points
    1 359
    Par défaut
    Citation Envoyé par ignis666 Voir le message
    Bonjours

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    01031. 00000 -  "insufficient privileges"

    Pomalaix a résumé ce que je voulais vous dire. A quoi bon vous donner la solution à ce problème si ce n'est vous aider à persister dans la mauvaise voie.

    Quelle est cette raison qui fait en sorte que vous ayez opté pour le dynamique SQL au lieu et place du SQL statique?

    Pour en revenir à votre problème, il faut savoir que dans une procédure les grants attribués via un role ne sont pas valables. Par exemple si vous êtes capable de créer une table/trigger en ligne de commande via un role, vous ne pouvez pas créér cette table/trigger au sein d'une procédure jusqu'à ce que ce privilège vous soit directement attribué

  6. #6
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    Citation Envoyé par Pomalaix Voir le message
    ...
    - pourquoi créer un déclencheur alors qu'un simple attribut DEFAULT sur la colonne produira le même résultat ?
    ...
    Ce n'est pas tout à fait vrai. Si l'update fournit nul pour la colonne en question alors ça sera nul et non pas sysdate.

  7. #7
    Rédacteur

    Homme Profil pro
    Consultant / formateur Oracle et SQL Server
    Inscrit en
    Décembre 2002
    Messages
    3 461
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Consultant / formateur Oracle et SQL Server

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 461
    Points : 8 079
    Points
    8 079
    Par défaut
    Citation Envoyé par mnitu Voir le message
    Ce n'est pas tout à fait vrai. Si l'update fournit nul pour la colonne en question alors ça sera nul et non pas sysdate.
    Vivement qu'Oracle invente les contraintes NOT NULL alors

  8. #8
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 388
    Points
    18 388
    Par défaut
    J'ajouterai que l'attribut DEFAULT ne sert que pour les INSERT et en aucun cas pour les UPDATE, ce que l'auteur cherche à automatiser, mais comme il a les deux dates (insert et update), on peut parfaitement l'utiliser pour la date d'insertion.


    S'il veut générer automatiquement les triggers de mise à jour j'imagine qu'il a beaucoup de tables et qu'il ne souhaite pas les faire une à une.

    Au lieu de faire une procédure et de l'appeler pour chaque table, autant tout faire dans le même bloc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    create table t1 (col int, insert_date date default sysdate, update_date date);
    create table t2 (col int, insert_date date default sysdate, update_date date);
     
    declare
        v$_requete    varchar2(150);
    begin
        for c in
        (
        select table_name
          from user_tables
         where table_name like 'T%'
        )
        loop
            v$_requete := 'CREATE OR REPLACE TRIGGER UPDATE_' || c.table_name ||
                          '_TRIGGER BEFORE UPDATE ON ' || c.table_name ||
                          ' FOR EACH ROW BEGIN :new.update_date := SYSDATE; END;';
            EXECUTE IMMEDIATE v$_requete;
        end loop;
    end;
     
    alter session set nls_date_format = 'dd/mm/yyyy hh24:mi:ss';
    -- Session altered.
     
    insert into t1 (col) values (1);
    -- 1 row created.
     
    select * from t1;
           COL INSERT_DATE           UPDATE_DATE          
    ---------- --------------------- ---------------------
             1 16/09/2011 17:36:53                        
     
    -- Attendre quelques secondes
     
    update t1 set col = 2;
    -- 1 row updated.
     
    select * from t1;
           COL INSERT_DATE           UPDATE_DATE          
    ---------- --------------------- ---------------------
             2 16/09/2011 17:36:53   16/09/2011 17:37:19

  9. #9
    Rédacteur

    Homme Profil pro
    Consultant / formateur Oracle et SQL Server
    Inscrit en
    Décembre 2002
    Messages
    3 461
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Consultant / formateur Oracle et SQL Server

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 461
    Points : 8 079
    Points
    8 079
    Par défaut
    Citation Envoyé par Waldar Voir le message
    ... pour les UPDATE, ce que l'auteur cherche à automatiser
    Gloups, faut que je trouve du destop pour les yeux, tellement j'étais convaincu qu'il s'agissait d'un INSERT ! (Je reviens vous voir après ma séance de flagellation...)

Discussions similaires

  1. Réponses: 4
    Dernier message: 14/02/2012, 11h23
  2. Réponses: 13
    Dernier message: 27/04/2011, 10h13
  3. Variable dynamique évaluable dans une procédure stockée
    Par fifrelin70 dans le forum Développement
    Réponses: 6
    Dernier message: 25/03/2011, 11h06
  4. Pb de création de vue dans une procédure stockée
    Par Guena5635 dans le forum MS SQL Server
    Réponses: 6
    Dernier message: 27/03/2008, 17h45
  5. SQL dynamique dans une procédure stockée
    Par Amnesiak dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 15/07/2005, 15h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo