sql >> Base de Datos >  >> RDS >> Oracle

Disparador para buscar duplicados

En general, no puede imponer este tipo de restricción en un disparador. Tendrías que usar una restricción.

El problema que enfrentará si intenta usar un disparador es que generalmente encontrará una excepción de "tabla mutante". En general, un activador de nivel de fila en la tabla A (es decir, properties ) no puede consultar la tabla A. Puede solucionar ese problema creando un paquete, creando una colección en ese paquete, inicializando la colección en un activador de declaración anterior, escribiendo las claves que se insertan o actualizan en la colección en un activador de nivel de fila , y luego iterando a través de los elementos de la colección en un disparador de declaración posterior y emitiendo DML apropiado contra la tabla. Esto, sin embargo, implica una gran cantidad de piezas en movimiento y una gran complejidad (aunque la complejidad se reduce si estás en 11g y puedes usar un disparador compuesto en su lugar).

Además, si intenta utilizar un disparador, encontrará problemas en entornos multiusuario. Si el usuario A inserta una fila en una sesión y el usuario B inserta una fila duplicada en una sesión diferente antes de que el usuario A se comprometa, el activador de ninguna sesión detectará la fila duplicada. Puede solucionar potencialmente este tipo de problema bloqueando explícitamente una fila en la tabla principal para serializar las inserciones en la tabla (haciendo que la aplicación sea más lenta y menos escalable intencionalmente). Pero una restricción sería una solución mucho más eficiente y práctica.

Dicho todo esto, si solo realiza inserciones de una sola fila utilizando INSERT ... VALUES sintaxis y se limita a una sola sesión, su activador parece funcionar

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'