2012-06-12 6 views
1

У меня есть следующий триггер, который срабатывает, когда updated становится Y. Я хотел бы вставить старые значения, только если значения не существуют в таблице my_hist. Если такая же запись существует, она не должна вставляться. Для этого лучше всего создать ли ограничение для проверки уникальности в таблице my_hist или проверить это условие в триггере? Если да, то как я могу сделать это в триггере?Вставить триггер для проверки уникального ограничения

Или можно проверить уникальное ограничение таблицы my_hist в триггере, чтобы он не вставлял повторяющиеся записи.

CREATE OR REPLACE TRIGGER mytrig 
    AFTER UPDATE 
    ON mytab 
    FOR EACH ROW 
WHEN (
new.updated = 'Y' 
    ) 
BEGIN 
    INSERT INTO my_hist 
     VALUES (
         :old.id, 
         :old.no,       
         :old.start_date, 
         :old.end_date, 
         SYSDATE 
       ); 
END mytrig; 
/

ответ

1

Вы можете изменить свой insert следующим образом, чтобы проверить, существует ли дубликат. Выбор предполагает, что первичный ключ my_hist равен id и start_date, измените предложение where not exists, чтобы использовать только значения первичного ключа, если они разные.

insert into my_hist 
select :old.id, :old.no, :old.start_date, :old.end_date, sysdate 
    from dual 
where not exists (select 1 
         from my_hist 
        where id = :old.id 
         and start_date = :old.start_date 
          ) 

Однако для этого требуется сканирование индекса, поэтому оно не является оптимальным.

Вместо этого пусть исключение будет поднято. Он явно назван: dup_val_on_index. Если это поднимается, просто игнорируйте его.

BEGIN 
    INSERT INTO my_hist 
     VALUES (
         :old.id, 
         :old.no,       
         :old.start_date, 
         :old.end_date, 
         SYSDATE 
       ); 
-- ignore an exception that get's raised if a duplicate value 
-- gets inserted. 
EXCEPTION WHEN DUP_VAL_ON_INDEX then null; 
END mytrig; 
+0

Спасибо за решение. Оценил. – user75ponic

3

Если вы хотите применить уникальность, используйте уникальное ограничение. Это всегда будет предпочтительнее кодировать что-то самостоятельно.

Вы можете проверить, существует ли уже строка, как часть вашего INSERT заявления

INSERT INTO my_hist(id, 
        no, 
        start_date, 
        end_date, 
        some_other_column) 
    SELECT :old.id, 
     :old.no, 
     :old.start_date, 
     :old.end_date, 
     sysdate 
    FROM dual 
    WHERE NOT EXISTS(SELECT 1 
         FROM my_hist 
         WHERE my_hist.id = :old.id 
         AND my_hist.no = :old.no 
         AND my_hist.start_date = :old.start_date 
         AND my_hist.end_date = :old.end_date); 

Это не будет работать, однако, в многопользовательской среде пользователя, где несколько сеансов могут вставить ту же строку в то же время ,

+0

Thanks Justin. Можно ли связать ограничение в триггере, чтобы я мог иметь условие в триггере, если ограничение нарушено, а не запускать триггер? – user75ponic

+0

@Polappan. У вас наверняка есть триггерная попытка выполнить «INSERT», а затем поймать исключение 'dup_val_on_index', которое будет выбрано, если ограничение будет нарушено. –

+0

Спасибо за комментарии и решение. Оценил. – user75ponic

Смежные вопросы