2016-07-20 1 views
0

J'ai de l'étiquette '2 tables et « musicien »déclenchement Oracle sur les valeurs varchar ne fonctionne pas

CREATE TABLE label 
(labId varchar(10) NOT NULL PRIMARY KEY, 
labName varchar(20) NOT NULL 
); 



CREATE TABLE musician 
(musId varchar(10) NOT NULL PRIMARY KEY, 
musName varchar(30) NOT NULL, 
labId varchar(10) NOT NULL, 
CONSTRAINT MusLabel FOREIGN KEY (labId) REFERENCES label(labId) 
); 

J'ai créé un déclencheur pour limiter le nombre de musiciens une étiquette peut avoir dans une plage de 1 à 5 ; de sorte que, par exemple une étiquette x ne peut pas avoir 6 musiciens:

CREATE OR REPLACE TRIGGER before_musician_insert 
BEFORE INSERT ON musician 
FOR EACH ROW 
DECLARE 
total integer; 
BEGIN 
SELECT COUNT(*) INTO total 
FROM musician, label 
WHERE musician.labId=label.labId; 
IF (total < 0 OR total > 5) 
THEN 
DBMS_OUTPUT.PUT_LINE('Invalid'); 
END IF; 
END; 
/

Lorsque j'insère un 6 musicien dans la table avec le même ID d'étiquette, l'instruction d'insertion ne « déclencheur » TRIGGER et la 6e valeur ajoutée à la table. Je ne sais pas comment résoudre ce problème. J'ai essayé une contrainte de vérification, mais avec des valeurs varchar, cela ne fonctionne pas non plus.

J'apprécie votre aide.

+0

Votre déclencheur n'a aucun sens. Tout d'abord, c'est sur la table des musiciens, mais vous décrivez le problème en tant qu'étiquettes. –

+0

Est-ce que c'est pour une classe où vous devez utiliser un déclencheur? Ce n'est pas une bonne utilisation pour un déclencheur (en particulier si vous prévoyez d'avoir plusieurs utilisateurs) et l'exigence n'a pas beaucoup de sens - que se passe-t-il si une étiquette veut signer un 6ème musicien? Si vous voulez vraiment imposer ce genre de chose, vous feriez mieux de changer le modèle de données. –

+0

@Justin Cave oui c'est une affectation pour une classe en fait. Je me demandais si je pouvais utiliser une contrainte de vérification dans ce cas, et si oui comment? – omar

Répondre

0

Votre code a plusieurs problèmes. Par exemple, il n'accède pas au :new. Le déclencheur est sur la mauvaise table. Il n'a aucune génération d'erreur.

je pourrais suggérer quelque chose comme ceci:

CREATE OR REPLACE TRIGGER before_labels_insert 
BEFORE INSERT ON labels 
FOR EACH ROW 
DECLARE 
    v_total integer; 
    user_xcep EXCEPTION; 
    PRAGMA EXCEPTION_INIT(user_xcep, -20001); 
BEGIN 

    SELECT COUNT(*) INTO v_total 
    FROM labels l 
    WHERE l.labId = :new.labId; 
    IF (v_total >= 5) THEN 
     DBMS_OUTPUT.PUT_LINE('Invalid'); 
     RAISE user_xcep 
    END IF; 
END; 
+0

Ce déclencheur génère une erreur de table mutante car la même table sur laquelle une instruction de déclenchement est activée est interrogée. Oui, le déclencheur de niveau de ligne 'before insert' va pardonner une simple instruction 'insert into .. values ​​()' mais l'instruction' insert into select ... from' échouera. De plus, je pense que si un déclencheur doit être créé, il doit être créé sur la table 'musiciens '. Sur la base de la description de l'OP, il y a une relation de un à plusieurs entre les labels et les musiciens. –

+0

@Gordon Linoff Je reçois le même résultat. Cela me permet d'insérer des valeurs> 5 dans la table. Peut-être devrais-je clarifier ma demande: ce que j'essaie de faire, c'est de limiter l'insertion sur la table des musiciens et non l'inverse, comme l'a justement souligné Nicholas Krasnov. – omar

0

Feux de déclenchement AVANT l'insert, de sorte que l'entrée sixième n'existe pas lorsque la requête est exécutée.

Si vous souhaitez une erreur sur l'insertion de la 6ème entrée, vous pouvez en faire un déclencheur AFTER (et déclencher une fois par instruction, plutôt que FOR EACH ROW).