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.