Oracle
 sql >> Base de données >  >> RDS >> Oracle

Déclencheur pour vérifier les doublons

Vous ne pouvez pas, en général, appliquer ce type de contrainte dans un déclencheur. Vous auriez besoin d'utiliser une contrainte.

Le problème auquel vous serez confronté si vous essayez d'utiliser un déclencheur est que vous rencontrerez généralement une exception "table en mutation". En général, un déclencheur au niveau de la ligne sur la table A (c'est-à-dire properties ) ne peut pas interroger la table A. Vous pouvez contourner ce problème en créant un package, en créant une collection dans ce package, en initialisant la collection dans un déclencheur d'instruction avant, en écrivant les clés qui sont insérées ou mises à jour dans la collection dans un déclencheur au niveau de la ligne , puis en parcourant les éléments de la collection dans un déclencheur d'instruction after et en émettant le DML approprié par rapport à la table. Ceci, cependant, implique beaucoup de pièces mobiles et beaucoup de complexité (bien que la complexité soit réduite si vous êtes sur 11g et que vous pouvez utiliser un déclencheur composé à la place).

De plus, si vous essayez d'utiliser un déclencheur, vous rencontrerez des problèmes dans les environnements multi-utilisateurs. Si l'utilisateur A insère une ligne dans une session et que l'utilisateur B insère une ligne en double dans une session différente avant que l'utilisateur A ne valide, aucun déclencheur de session ne détectera la ligne en double. Vous pouvez potentiellement contourner ce type de problème en verrouillant explicitement une ligne dans la table parent afin de sérialiser les insertions dans la table (ce qui rend intentionnellement l'application plus lente et moins évolutive). Mais une contrainte serait une solution beaucoup plus efficace et pratique.

Cela étant dit, si vous ne faites que des insertions sur une seule ligne en utilisant le INSERT ... VALUES syntaxe et limitez-vous à une seule session, votre déclencheur semble fonctionner

SQL> ed
Wrote file afiedt.buf

  1  create table Properties(
  2          idProperties number(10) NOT NULL,
  3          Address_FK number(20),
  4          Ownership_FK number(20)
  5* )
SQL> /

Table created.

SQL> CREATE OR REPLACE TRIGGER Check_Duplicate
  2  before insert or update on properties
  3  FOR each ROW
  4
  5  declare
  6  v_dup number;
  7
  8  begin
  9      select count(idProperties) INTO v_dup from properties where Address_FK=
:NEW.Address_FK and
 10       Ownership_FK=:NEW.Ownership_FK;
 11
 12   if v_dup > 0 then
 13     Raise_Application_Error (-20100, 'This property already exists. The inse
rt is cancelled.');
 14  end if;
 15  end;
 16  /

Trigger created.

SQL> insert into properties values( 1, 10, 100 );

1 row created.

SQL> insert into properties values( 2, 10, 100 );
insert into properties values( 2, 10, 100 )
            *
ERROR at line 1:
ORA-20100: This property already exists. The insert is cancelled.
ORA-06512: at "SCOTT.CHECK_DUPLICATE", line 9
ORA-04088: error during execution of trigger 'SCOTT.CHECK_DUPLICATE'