À l'aide de if EXISTS (SELECT ...) dans un AVANT déclencheur d'INSERTION (Oracle)
Le code que j'ai ne fonctionne pas, Oracle me dit que le déclencheur a été créé pour les erreurs de compilation. Apparemment je ne peux pas obtenir tout renseignements plus précis sur ce que l'erreur de build est...
Je n'ai pas fait beaucoup de SQL avant, donc je ne suis pas familier avec la syntaxe. J'ai un pressentiment que c'est mon if EXISTS (SELECT ...) ENSUITE relevé que l'Oracle n'aime pas, j'ai cherché sur Google pour des exemples de ce genre, mais je ne pouvais pas vraiment trouver quelque chose qui a fonctionné dans mon cas.
Donc sur le code:
- "débuts" est un attribut de date (début)
- "fin" est un autre attribut de date (fin)
- Je veux assurez-vous que la NOUVELLE ligne dates ne se chevauchent pas avec toute autre ligne dans le tableau si ces 2 lignes ont la même "numInfirmier" attribut.
- Donc je sélectionne toutes les lignes qui ont le même numInfirmier que la NOUVELLE ligne et les dates se chevauchent.
- Et SI quelque chose EXISTE dans que choisir, je lève une erreur.
CREATE OR REPLACE TRIGGER chev_surv BEFORE INSERT OR UPDATE ON surveillance FOR EACH ROW BEGIN IF EXISTS ( SELECT * FROM surveillance WHERE surveillance.numInfirmier = :NEW.numInfirmier AND ((surveillance.debut > :NEW.debut AND surveillance.debut < :NEW.fin) OR (surveillance.fin > :NEW.debut AND surveillance.fin < :NEW.fin)) ) THEN RAISE_APPLICATION_ERROR(-20001, 'Il ne doit pas y avoir de chevauchement entre deux périodes surveillance pour un surveillant.'); END IF; END; /
Aucune idée de quel est le problème?
Vous pouvez obtenir des renseignements plus précis sur les erreurs réelles avec
Ah la vache, c'est une bonne chose à savoir XD
"afficher l'erreur", dit je ne peux utiliser "EXISTE" dans une instruction SQL.... wut?
Vous essayez de l'utiliser dans une PL/SQL contexte; c'est une autre (bien que souvent se chevauchent) de la langue. Vous pouvez utiliser seulement dans une sous-requête, comme
show errors
si votre client prend en charge, ou select * from user_errors where type = 'TRIGGER' and name = 'CHEV_SURV'
. Qui est disponible pour toutes stockées PL/SQL. Vous avez raison, vous ne pouvez pas utiliser exists
à l'extérieur d'un select
condition. Mais même si vous l'obtenez à compiler, vous obtiendrez une mutation erreur de table: vous ne pouvez pas interroger la table le déclencheur est contre.Ah la vache, c'est une bonne chose à savoir XD
"afficher l'erreur", dit je ne peux utiliser "EXISTE" dans une instruction SQL.... wut?
Vous essayez de l'utiliser dans une PL/SQL contexte; c'est une autre (bien que souvent se chevauchent) de la langue. Vous pouvez utiliser seulement dans une sous-requête, comme
select ... from ... where exists (select ... from ...)
. Justin réponse vous montre comment vous devez vérifier dans ce cas, et pourquoi cela ne fonctionne toujours pas *8-)OriginalL'auteur MademoiselleC | 2014-03-28
Vous devez vous connecter pour publier un commentaire.
Tout d'abord, si vous êtes à l'aide de SQL*Plus, lorsque vous créez un objet et dit qu'il y a des erreurs de compilation, la commande
show errors
vous montrera les erreurs.Si vous avez exécuté
show errors
, vous auriez dit queIF EXISTS
n'est pas valide la syntaxe. Vous pourriez faire quelque chose commeUne fois que vous avez corrigé l'erreur de compilation, cependant, vous vous retrouverez avec des erreurs d'exécution. Dans une ligne de niveau de déclenchement sur
surveillance
, vous ne pouvez pas généralement requêtesurveillance
(vous pouvez si tout ce que vous faites est unINSERT VALUES
qui est garanti pour seulement insérer une seule ligne). Si vous le faites, vous obtiendrez une mutation de déclencher d'erreur lors de l'exécution.À partir d'un modèle de données de point de vue, quand vous trouvez vous-même la conception d'une table dans laquelle les données valides pour une ligne particulière dépend des données stockées dans d'autres lignes de la même table, vous avez généralement violé les principes de normalisation et vous êtes généralement mieux servi fixant le modèle de données sous-jacente.
Si vous êtes vraiment déterminé à garder le modèle de données, je préfère créer une vue matérialisée qui actualise sur le commit qui a des données uniquement pour les lignes qui portent atteinte à vos critères. Vous pouvez ensuite mettre des contraintes sur que la vue matérialisée que de générer des erreurs au moment de la validation lors de vos critères ne sont pas respectés. Cela nécessitera de la vue matérialisée journaux sur votre table.
Si vous voulez vraiment garder le modèle de données et que vous voulez appliquer la logique avec les déclencheurs, vous devez le classique trois déclencher la solution (ou un composé de déclenchement avec trois pièces si vous utilisez 11.2 ou plus tard). Vous devez créer un package avec une collection de valeurs de clé primaire. Un avant l'énoncé déclencheur devrait initialiser la collection. Une ligne de niveau de déclenchement à insérer les clés primaires des lignes qui ont été insérés et/ou mis à jour dans cette collection. Et puis un après l'énoncé déclencheur itérer sur cette collection et mettre en œuvre les contrôles que vous souhaitez. C'est beaucoup de pièces en mouvement, mais, ce qui est pourquoi je le déconseille.
Plus, même si vous avez toutes ces pièces de travail, votre logique de ne pas vous protéger dans un environnement multi-utilisateur. Lorsque vous avez plusieurs utilisateurs en appuyant sur le système dans le même temps, il est tout à fait possible qu'un utilisateur insère une ligne, la deuxième utilisateur insère une autre ligne avec une zone de chevauchement, et ensuite, chaque séance s'engager. Dans ce cas, les deux ensembles de déclencheurs permettra le changement mais vous serez toujours à gauche avec les données de la table qui porte atteinte à vos exigences. La vue matérialisée, car elle est appliquée au moment de la validation, plutôt qu'au moment de l'insertion, de fonctionner correctement dans un environnement multi-utilisateur. Si vous voulez que les déclencheurs de travailler dans un environnement multi-utilisateur, vous auriez à compliquer en ajoutant des supplémentaires de la logique qui impose de sérialisation qui pourrait bloquer la deuxième session du
insert
de courir jusqu'à la première session soit validée ou annulée. Qui ajoute à la complexité, réduit l'évolutivité, et selon comment il est mis en œuvre, de faire un cauchemar de soutien.Il n'y a vraiment aucun moyen de l'obtenir avec un seul déclencheur? Pour une raison que je doute vraiment les enseignants attendent de nous de venir avec un 3 déclencheur solution...
Pas avec un seul déclencheur, pas. Vous pouvez créer un déclencheur qui a déclenché uniquement sur
insert
, pasupdate
, et de limiter votre application pour faireinsert ... values
opérations (insert ... select
serait encore jeter une mutation des erreurs de déclenchement) et ensuite seulement 1 déclencheur. Ce n'est pas une restriction que vous aurez jamais envisager d'imposer sur un système réel, mais peut-être que c'est ce que votre instructeurs sont à la recherche pour.La situation que nous avons reçu est uniquement de la recherche (c'est à dire certainement pas censé correspondre aux objectifs d'un système réel), donc je pense que ce serait une solution acceptable. Et le meilleur de tous, c'est celui que je peux le faire très rapidement. Merci pour l'aide!
OriginalL'auteur Justin Cave