Триггер для проверки на дубликаты - PullRequest
2 голосов
/ 13 декабря 2011

Я пишу триггер, и у меня возникла проблема. Триггер выполняется и компилируется без ошибок, но по некоторым причинам он не выполняет работу, которую я хочу. Если бы кто-то мог мне помочь.

Вот вопрос:

Запишите триггер, который будет выполнен при вставке, обновлении НЕДВИЖИМОСТИ. Каждое введенное свойство проверяется на соответствие другим свойствам: агент (ы), владелец (и), адрес, если вы его найдете, то обновите статус свойства на «Двойной» как дубликат.

Я вставляю те же данные, и они позволяют мне это делать, но обычно это не так!

Вот мои таблицы:

create table Properties(  
            idProperties number(10) NOT NULL,
        Type varchar2(45) NOT NULL,
        SquareMeters varchar2(10) NOT NULL,
        Rooms number(10) NOT NULL,
        ConstructionDate date NOT NULL,
        FloorLocation varchar(20),
        Price number(10) NOT NULL,
        CityView varchar2(20),
        DateOfInsert date NOT NULL,
        DateOfExiration date NOT NULL,
        Address_FK number(20),
        Service_FK number(20),
        Ownership_FK number(20),
        Status_FK number(20),
        PropertyService_FK number(20))

create table Address(
          idAddress number(10) NOT NULL,
          address_name varchar2(20),
          City_FK number(20))


create table OwnerAgent(
           idOwnerAgent number(10) NOT NULL,
           Name varchar2(50)  NOT NULL,
           LastName varchar2(50)  NOT NULL,
           PhoneNr number(20),  
           Email varchar2(20),
           Sex varchar2(10),
           Profesion varchar2(20),
           Birthdate date,
           LastLogInDate date NOT NULL,
           Status varchar2(20),
           Address_FK number(20))

create table Ownership(
            idOwnership number(10) NOT NULL,
            PercentageOwed number(10)NOT NULL,
            RequiredPercentage number(10) NOT NULL,
        OwnerAgent_FK number(20))

Вот мой триггер:

CREATE OR REPLACE TRIGGER Check_Duplicate
before insert or update on properties
FOR each ROW

declare
v_dup number;

begin
    select count(idProperties) INTO v_dup from properties where Address_FK=:NEW.Address_FK and 
     Ownership_FK=:NEW.Ownership_FK;

 if v_dup > 0 then
   Raise_Application_Error (-20100, 'This property already exists. The insert is cancelled.');
end if;
end;

Спасибо.

Ответы [ 2 ]

5 голосов
/ 13 декабря 2011

В общем случае вы не можете применить такое ограничение в триггере.Вам нужно будет использовать ограничение.

Проблема, с которой вы столкнетесь, если попытаетесь использовать триггер, состоит в том, что вы, как правило, сталкиваетесь с исключением из таблицы «Мутирующая таблица».Как правило, триггер уровня строки в таблице A (т. Е. properties) не может запросить таблицу A. Вы можете обойти эту проблему, создав пакет, создав коллекцию в этом пакете, инициализировав коллекцию в триггере оператора before, написавключи, которые вставляются или обновляются в коллекции в триггере уровня строки, а затем перебирают элементы коллекции в триггере после оператора и выдают соответствующий DML для таблицы.Это, однако, включает в себя много движущихся частей и много сложности (хотя сложность уменьшается, если вы на 11g и можете вместо этого использовать составной триггер).

Дополнительно, если вы пытаетесьиспользуйте триггер, вы столкнетесь с проблемами в многопользовательской среде.Если пользователь A вставляет строку в один сеанс, а пользователь B вставляет дублирующую строку в другой сеанс до того, как пользователь A фиксирует, ни один из триггеров сеанса не обнаружит дублирующую строку.Вы можете потенциально обойти эту проблему, явно заблокировав строку в родительской таблице, чтобы сериализовать вставки в таблицу (намеренно делая приложение медленнее и менее масштабируемым).Но ограничение было бы гораздо более эффективным и практичным решением.

Все это, как говорится, если вы делаете только однострочные вставки с использованием синтаксиса INSERT ... VALUES и ограничиваетесь одним сеансом, ваш триггер действительно появляетсяна работу

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'
1 голос
/ 13 декабря 2011

Назначение говорит, чтобы изменить статус, чтобы удвоить, если дублировать, а не предотвратить это

CREATE OR REPLACE TRIGGER Check_Duplicate
before insert or update on properties
FOR each ROW

declare
v_dup number;

begin
    select count(idProperties) INTO v_dup from properties where Address_FK=:NEW.Address_FK and 
     Ownership_FK=:NEW.Ownership_FK;

 if v_dup > 0 then
   :New.Status :='DOUBLE'
end if;
end;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...