Oracle триггер, чтобы предотвратить вставку новой строки при условии - PullRequest
0 голосов
/ 08 июня 2018

Я нашел несколько вопросов, касающихся одного и того же вопроса, но без лучшего решения.Мне нужно создать триггер Oracle, который будет предотвращать новые вставки при условии, но тихо (без возникновения ошибки).

Пример: мне нужно прекратить вставку строк только с баром = 'FOO'.(Я не могу редактировать ограничения таблицы, не могу получить доступ к процедуре, которая действительно выполняет вставку и т. Д., Поэтому триггер является единственной опцией)

Решения пока подтверждают, что это невозможно.Одним из многообещающих предложений было создание промежуточной таблицы, вставка ключевых значений в это значение, когда bar = 'FOO', а затем удаление этих записей из исходной таблицы после завершения вставки, что, по-моему, неверно.Любой ответ будет высоко оценен.

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

Один из способов - скрыть ряд.Начиная с 12c, это достаточно просто:

create table demo
( id integer primary key
, bar varchar2(10) );

-- This adds a hidden column and registers the table for in-database archiving:
alter table demo row archival;

-- Set the hidden column to '1' when BAR='FOO', else '0':
create or replace trigger demo_hide_foo_trg
before insert or update on demo
for each row
begin
    if :new.bar = 'FOO' then
        :new.ora_archive_state := '1';
    else
        :new.ora_archive_state := '0';
    end if;
end demo_hide_foo_trg;
/

-- Enable in-database archiving for the session
-- (probably you could set this in a log-on trigger):
alter session set row archival visibility = active;

insert into demo (id, bar) values (1, 'ABC');
insert into demo (id, bar) values (2, 'FOO');
insert into demo (id, bar) values (3, 'XYZ');

commit;

select * from demo;

      ID BAR
-------- --------
       1 ABC
       3 XYZ

-- If you want to see all rows (e.g. to delete hidden rows):
alter session set row archival visibility = all;

В более ранних версиях Oracle вы могли добиться того же с помощью политики безопасности.

Другим способом может быть добавление флага 'required'который по умолчанию равен «Y» и имеет значение «N» в триггере, когда bar = 'FOO', и (при условии, что вы не можете изменить приложение для использования представления и т. д.) второй триггер удаляет все такие строки (или, возможно, лучше, переместите их в архивную таблицу).

create table demo
( id integer primary key
, bar varchar2(10) );

alter table demo add required_yn varchar2(1) default on null 'Y';

create or replace trigger demo_set_not_required_trg
before insert or update on demo
for each row
begin
    if :new.bar = 'FOO' then
        :new.required_yn := 'N';
    end if;
end demo_hide_foo_trg;
/

create or replace trigger demo_delete_not_required_trg
after insert or update on demo
begin
    delete demo where required_yn = 'N';
end demo_delete_not_required_trg;
/
0 голосов
/ 11 июня 2018

По-видимому, невозможно использовать триггер, чтобы остановить вставки, не вызывая исключение.

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

Как минимальный макет для вашей текущей таблицы.myrole - это просто замена привилегий, предоставленных для таблицы:

CREATE ROLE myrole;

CREATE TABLE mytable (
  bar VARCHAR2(30)
);
GRANT ALL ON mytable TO myrole;

Теперь вы переименовываете таблицу и убеждаетесь, что никто больше не сможет получить к ней прямой доступ, и замените ее представлением.Это представление может быть защищено вместо триггера:

REVOKE ALL ON mytable FROM myrole;
RENAME mytable TO myrealtable;

CREATE OR REPLACE VIEW mytable AS SELECT * FROM myrealtable;
GRANT ALL ON mytable TO myrole;

CREATE OR REPLACE TRIGGER myioftrigger 
  INSTEAD OF INSERT ON mytable
  FOR EACH ROW
BEGIN
  IF :new.bar = 'FOO' THEN
    NULL;
  ELSE 
    INSERT INTO myrealtable(bar) VALUES (:new.bar);
  END IF;
END;
/

Итак, если кто-то вставляет нормальную строку в поддельное представление, данные вставляются в вашу реальную таблицу:

INSERT INTO mytable(bar) VALUES('OK');
1 row inserted.

SELECT * FROM mytable;
OK

Но если кто-то вставляет магическое значение 'FOO', триггер молча глотает его, и в реальной таблице ничего не меняется:

INSERT INTO mytable(bar) VALUES('FOO');
1 row inserted.

SELECT * FROM mytable;
OK

Внимание: если вы хотите защитить свою таблицу также от ОБНОВЛЕНИЙвам нужно будет добавить второй триггер для обновлений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...