J'ai 3 tableaux: Projets
, Composants
et Fournisseurs
.
Ce que j'essaie de faire, c'est d'écrire un déclencheur qui ne permet pas de modifier la valeur de city
si le composant et le projet ont la même ville que le fournisseur.
Ce que j'ai essayé jusqu'à présent:
Error at line 3: PL/SQL: SQL Statement ignored
Après avoir essayé d'exécuter ceci, j'obtiens l'erreur suivante:
Error at line 3: PLS-00103: Encountered the symbol "JOIN" when expecting one of the following: ) , with group having intersect minus order start union where connect
Veuillez noter que le numéro de ligne fait référence au nombre de la ligne après BEGIN!
J'ai également essayé d'écrire la partie declare avant BEGIN, j'obtiens l'erreur suivante:
create or replace TRIGGER Supplier_control BEFORE UPDATE of city ON Suppliers BEGIN DECLARE v_counter NUMBER := 0; SELECT COUNT(*) FROM (SELECT * FROM Suppliers s JOIN Projects p ON (s.city=p.city) JOIN Components c ON (c.city=s.city)) INTO v_counter; IF (v_counter != 0) THEN raise_application_error(-20111,'Can't change the city for this supplier!'); END IF; END;
Ce qui doit être fait afin de se débarrasser de ces erreurs?
4 Réponses :
Vous essayez d'accéder à la variable qui est assignée à zéro dans la déclaration. définir la variable à partir de la requête (le résultat sera un nombre)
create or replace TRIGGER Supplier_control BEFORE UPDATE of city ON Suppliers BEGIN DECLARE v_counter NUMBER := 0; -- change this line SET v_counter = (SELECT COUNT(*) FROM (SELECT * FROM Suppliers s JOIN Projects p ON (s.city=p.city) JOIN Components c ON (c.city=s.city))); IF (v_counter != 0) THEN raise_application_error(-20111,'Can't change the city for this supplier!'); END IF; END;
a changé la requête de comptage en une requête modifiée. Exécutez d'abord simplement la requête SELECT COUNT (*) FROM (SELECT * FROM Fournisseurs s JOIN Projects p ON (s.city = p.city) JOIN Components c ON (c.city = s.city)) code > si la sortie est un nombre alors affectez à la variable
v_counter
Merci pour votre réponse! J'ai essayé cela mais j'obtiens toujours cette erreur qui indique qu'il a rencontré JOIN alors qu'il attendait autre chose
Exécutez d'abord simplement la requête SELECT COUNT (*) FROM (SELECT * FROM Fournisseurs s JOIN Projects p ON (s.city = p.city) JOIN Components c ON (c.city = s.city)) code > si la sortie est un nombre alors affectez à la variable
v_counter
Il y a des erreurs de syntaxe.
DECLARE
précède l'instruction BEGIN
. INTO
va après SELECT
et avant FROM
. rise_application_error (-20111, 'Impossible de changer la ville pour ce fournisseur!');
vous ne pouvez pas écrire Can't
car le premier guillemet simple se terminera à la citation de Can't
provoquant la fin de la chaîne. Vous devez donc le supprimer ou faire: rise_application_error (-20111, 'Impossible de changer la ville pour ce fournisseur!');
Cela dit, le code complet devrait ressembler à:
CREATE OR REPLACE TRIGGER Supplier_control BEFORE UPDATE of city ON Suppliers DECLARE v_counter NUMBER := 0; BEGIN SELECT COUNT(*) INTO v_counter FROM (SELECT * FROM Suppliers s JOIN Projects p ON s.city=p.city JOIN Components c ON c.city=s.city); IF v_counter != 0 THEN raise_application_error(-20111,'Can''t change the city for this supplier!'); END IF; END;
J'espère que cela vous aidera.
Vérifiez, par lower ()
ou upper ()
pour faire correspondre, y compris insensibilité à la casse, si une ville correspond à l'ensemble des valeurs du projet du tableau.
Vous ne le faites pas. Il n'est pas nécessaire et ne doit pas utiliser la table Supplier dans l'instruction select en raison du risque que le nom de la table soit une erreur de mutation:
CREATE OR REPLACE TRIGGER Supplier_control BEFORE UPDATE of city ON Suppliers DECLARE v_counter PLS_INTEGER; BEGIN SELECT COUNT(*) INTO v_counter FROM Projects p WHERE lower(:new.city)=lower(p.city); IF (v_counter != 0) THEN raise_application_error(-20111,'Can''t change the city for this supplier!'); END IF; END;
où une initialisation est redondante pour v_counter
, s'il n'y a pas d'enregistrement correspondant trouvé, il serait déjà nul. De plus, notez l'ordre du mot-clé declare
, y compris une partie de définition de variable.
Il n'y a pas besoin de frais généraux d'une jointure ni même de transfert d'aucune date. En supposant que City soit indexé dans les projets et les composants (devrait probablement être un FK indexé), ce qui suit ne nécessite qu'un simple test d'index sur chaque table.
create or replace trigger supplier_control before update of city on suppliers for each row declare project_component_exists integer ; begin select null into project_component_exists from dual where exists ( select null from projects where city = :old.city ) and exists ( select null from components where city = :old.city ); raise_application_error(-20111,'Can''t change the city for this supplier!'); exception when no_data_found then null; end;
Dans votre cas, plutôt que de créer un déclencheur qui ne permet pas la mise à jour, vous devez avoir créé un déclencheur qui aurait mis à jour l'autre table de remorquage, cela aurait été une conception robuste.