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

PL/SQL Oracle Discussion :

Emulation contrainte check avec fonction


Sujet :

PL/SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre extrêmement actif
    Avatar de randriano
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 221
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 221
    Par défaut Emulation contrainte check avec fonction
    Bonjour,

    Voici mon code
    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
    SET SERVEROUTPUT ON
    /
    create table RANDRIANO.DRIA_TEST (
    	"ID" varchar2(38),
    	"CONTENT" varchar2(38) NOT NULL,
    	"MYVALUE" INT,
    	"SYSTEM" NUMBER (38) DEFAULT 0,
    	CONSTRAINT "PK_DRIA_TEST" PRIMARY KEY(ID) 
        USING INDEX TABLESPACE RANDRIANOINDEX
        ) TABLESPACE RANDRIANODATA 
        LOGGING
    /
    CREATE OR REPLACE TRIGGER RANDRIANO.B_I_DRIA_TEST
    before
    INSERT ON RANDRIANO.DRIA_TEST 
    FOR EACH ROW
    DECLARE
    v_value int;
    BEGIN
     
      v_value := :new.MYVALUE;
     
      dbms_output.put_line('ligneAvant.MYVALUE = ' || v_value);
     
    	if (v_value <> 0 or v_value <>1) then
     
        raise_application_error(-20000,'Check_DRIA_TEST');
     
      end if   ;
     
    END ;
    J'émule donc la contrainte CHECK avec un trigger: ici, on a un simple CHECK sans fonction (MYVALUE <> 0 or MYVALUE <>1)

    Je teste la requête:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    insert into RANDRIANO.DRIA_TEST values('KUAKO','lalala',0,5)
    Ici, j'ai MYVALUE = 1 respectant la contrainte, le dbms_output.put_line l'affiche même mais j'ai toujours
    ERROR at line 1:
    ORA-20000: Check_DRIA_TEST
    ORA-06512: at "RANDRIANO.B_I_DRIA_TEST", line 11
    ORA-04088: error during execution of trigger 'RANDRIANO.B_I_DRIA_TEST'
    randriano.dvp.com
    Développeur. Product Owner [Agile]. Sites web, mobile apps, système d'information (SI).

  2. #2
    Membre extrêmement actif
    Avatar de randriano
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 221
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 221
    Par défaut
    Il semble (et testé) que ceci marche
    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
    DECLARE
    v_value int;
    BEGIN
     
      v_value := :new.MYVALUE;
     
      dbms_output.put_line('ligneAvant.MYVALUE = ' || v_value);
     
    	if ((v_value = 0) or (v_value = 1)) then
     
    	  null;
     
    	else
        raise_application_error(-20000,'Check_DRIA_TEST');
     
      end if   ;
     
    END ;
    Quelle gaffe de ma part: <> et != ne marchent pas avec INT !!!

    Donc, l'émulation de la contrainte est donc un TRIGGER BEFORE INSERT (mais aussi BEFORE UPDATE), FOR EACH ROW doit être présent
    randriano.dvp.com
    Développeur. Product Owner [Agile]. Sites web, mobile apps, système d'information (SI).

  3. #3
    McM
    McM est déconnecté
    Expert confirmé

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par randriano Voir le message
    Il semble (et testé) que ceci marche

    Quelle gaffe de ma part: <> et != ne marchent pas avec INT !!!
    C'est pas ça, c'est ton test qui est foireux.

    Ce serait plutôt
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    IF v_value NOT IN (0,1) THEN RAISE
    Mais attention, il faut tester le NULL.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    IF NVL(v_value,-1) NOT IN (0,1) THEN RAISE

  4. #4
    Membre extrêmement actif
    Avatar de randriano
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 221
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 221
    Par défaut
    Merci McM pour la syntaxe correcte !

    J'ai une question concernant la nécessité d'un trigger sans AFTER EACH ROW, l'avec after each row n'est-il pas le standard? la différence c'est qu'il n'y a pas seulement de old et new
    randriano.dvp.com
    Développeur. Product Owner [Agile]. Sites web, mobile apps, système d'information (SI).

  5. #5
    McM
    McM est déconnecté
    Expert confirmé

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Billets dans le blog
    4
    Par défaut
    LA différence, c'est que l'un se lance 1 seule fois pour un ordre, l'autre se lance pour chaque ligne.

    Donc pour un insert into select *, le trigger BEFORE INSERT ne s'exécutera qu'une seule fois, le trigger BEFORE INSERT FOR EACH ROW s'exécutera autant de fois qu'il y a de lignes.

  6. #6
    Membre extrêmement actif
    Avatar de randriano
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 221
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 221
    Par défaut
    Bof, je n'avais pas pensé à ce cas: "insert into select *"
    Donc, les autres SGBD qui n'ont donc que le trigger ligne ne sont pas vraiment optimisés comme le cas de SQL Server et MySql 5.1 ????
    randriano.dvp.com
    Développeur. Product Owner [Agile]. Sites web, mobile apps, système d'information (SI).

  7. #7
    Membre éclairé Avatar de rvfranck
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2004
    Messages
    746
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 746
    Par défaut
    Citation Envoyé par McM Voir le message
    LA différence, c'est que l'un se lance 1 seule fois pour un ordre, l'autre se lance pour chaque ligne.

    Donc pour un insert into select *, le trigger BEFORE INSERT ne s'exécutera qu'une seule fois, le trigger BEFORE INSERT FOR EACH ROW s'exécutera autant de fois qu'il y a de lignes.
    J'ai toujours su la différence entre les deux mais j'ai jamais vraiment compris: est ce que cela veut dire que lorsque l'on insert une seule ligne a la fois on peut utiliser les deux (le resultat est le même), mais que lorsque l'on insert plusieurs lignes à la fois il faut "impérativement" utiliser FOR EACH ROW?

    A vous lire.

  8. #8
    McM
    McM est déconnecté
    Expert confirmé

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Billets dans le blog
    4
    Par défaut

    Ben oui c'est normal, 1 <> 0

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    IF (v_value <> 0 OR v_value <>1) then raise ...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Emuler contrainte CHECK
    Par CinePhil dans le forum SQL Procédural
    Réponses: 2
    Dernier message: 22/08/2010, 09h39
  2. contrainte check et fonction
    Par r83 dans le forum SQL
    Réponses: 3
    Dernier message: 05/01/2010, 07h46
  3. Probleme pour une contrainte CHECK avec MySQL
    Par dave260888 dans le forum Requêtes
    Réponses: 2
    Dernier message: 18/07/2008, 22h11
  4. Mettre un intervall avec une contrainte check
    Par vodevil dans le forum MS SQL Server
    Réponses: 6
    Dernier message: 06/12/2006, 06h32
  5. contraint CHECK avec lecture de données sur une autre table ?
    Par mamiberkof dans le forum Langage SQL
    Réponses: 1
    Dernier message: 22/05/2006, 09h14

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