2012-02-14 2 views
1

Я хотел бы вставить строку в таблицу истории, когда любой столбец обновлен в таблице.PL SQL-триггер для вставки истории записи при обновлении столбца

Я просто ищу, чтобы захватить имя столбца, старое значение и новое значение.

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

Я знаком с триггерами и с тем, как фиксировать обновления на одном столбце. Я специально ищу, как написать один триггер, который вставляет запись в таблицу истории для любой столбец, который обновляется в соответствующей таблице таблицы истории.

EDIT 1
Я не сказал НИГДЕ в моем посте, что я ищу исходный код так стыдно, что кто-downvotes меня и думает, что я ищу это. Вы можете проверить мои предыдущие вопросы/ответы, чтобы увидеть, что я не ищу «бесплатный исходный код».

Как я заявил в своем первоначальном вопросе, я ищу , как, чтобы написать это. Я исследовал http://plsql-tutorial.com/plsql-triggers.htm, и есть блок кода, который показывает, как писать триггер, когда обновляется столбец ONE. Я подумал, что, возможно, кто-то будет иметь ноу-хау, чтобы дать направление на более общий триггер для сценария, который я представил.

+1

Право. Хочешь знать, сколько я плачу в час? SO не является бесплатной услугой кодирования. что ты уже испробовал? –

+0

@Adrian - просто ищу здесь небольшое направление ... мой вопрос никогда не заявляет, что я ищу кого-нибудь, чтобы написать код для меня ... –

+0

Достаточно честный. Проблема в том, что ваш вопрос звучит точно так же, как в документе Spec, который я читаю сейчас. Вы должны нам что-то дать. У вас хоть какой-то подход? Вы исследовали, возможно ли это? Вы исследовали, что RDBMS (oracle) уже предоставляет это? –

ответ

9

Предполагая, что для обычного стола, а не для таблицы объектов, у вас нет большого количества опций. Ваш триггер должен быть чем-то вроде формы

CREATE OR REPLACE TRIGGER trigger_name 
    AFTER UPDATE ON table_name 
    FOR EACH ROW 
BEGIN 
    IF(UPDATING('COLUMN1')) 
    THEN 
    INSERT INTO log_table(column_name, column_value) 
     VALUES('COLUMN1', :new.column1); 
    END IF; 

    IF(UPDATING('COLUMN2')) 
    THEN 
    INSERT INTO log_table(column_name, column_value) 
     VALUES('COLUMN2', :new.column2); 
    END IF; 

    <<repeat for all columns>> 
END; 

Вы могли бы принести COLUMN1, COLUMN2 ... COLUMN<<n>> строки из словаря данных (USER_TAB_COLS), а не жесткого кодирования их, но вы все равно придется hard-code ссылки на столбцы в псевдозаписке :new.

Вы могли бы потенциально написать кусок кода, который генерируется на курок выше, запрашивая словаря данных (USER_TAB_COLS или ALL_TAB_COLS скорее всего), строит строку с утверждением DDL, а затем делать в EXECUTE IMMEDIATE выполнить оператор DDL. Затем вам нужно будет вызвать этот скрипт каждый раз, когда новый столбец будет добавлен в любую таблицу для повторного создания триггера для этого столбца. Это утомительно, но не особенно технически сложно писать и отлаживать такой код генерации DDL. Но это редко стоит того, потому что кто-то неизбежно добавляет новый столбец и забывает перезапустить сценарий, или кому-то нужно изменить триггер, чтобы выполнить некоторую дополнительную работу, и проще просто вручную обновить триггер, чем модифицировать и протестировать сценарий, который генерирует триггеры.

В целом, однако, я бы поставил под вопрос мудрость хранения данных таким образом. Сохранение одной строки в таблице истории для каждого столбца каждой модифицированной строки делает использование данных истории очень сложным. Если кто-то хочет знать, в каком состоянии находится определенная строка в определенный момент времени, вам придется присоединиться к таблице истории к себе N раз, где N - количество столбцов в таблице в этот момент времени. Это будет ужасно неэффективно, что очень быстро заставит людей избегать попыток использовать данные истории, потому что они не могут делать полезные вещи с ним в течение разумного периода времени, не разрывая их волосы.Как правило, гораздо эффективнее иметь таблицу истории с тем же набором столбцов, что и в живой таблице (с несколькими добавленными для дат отслеживания и т. П.) И вставлять одну строку в таблицу истории каждый раз, когда строка обновляется. Это будет потреблять больше места, но, как правило, гораздо проще в использовании.

И Oracle имеет ряд способов аудита изменений данных - вы можете использовать DML, вы можете использовать мелкозернистый аудит (FGA), вы можете использовать Workspace Manager, или вы можете использовать Oracle Total Recall. Если вы ищете большую гибкость, чем создание собственного кода запуска, я бы настоятельно предложил исследовать эти другие технологии, которые по своей сути гораздо более автоматизированы, чем пытаться разработать собственную архитектуру.

+0

Фантастический ответ и направление - спасибо. –

+0

Отличный ответ, как обычно – tbone

4

Вы можете настроить таблицу истории как SAME как основную таблицу + поле даты и типа. Вам нужно только захватить старые значения, так как новые значения находятся в главной таблице.

попробовать это (непроверенные):

create or replace trigger "MY_TRIGGER" 
before update or delete 
on MY_TABLE referencing new as new old as old 
for each row 
declare 
    l_dml_type varchar2(10); 
begin 
if (updating) then 
    l_dml_type := 'UPD'; 
else 
    l_dml_type := 'DEL'; 
end if; 

insert into MY_TABLE_HIST 
(
col1, 
col2, 
col3, 
dml_type, 
dml_date 
) 
values 
(
:old.col1, 
:old.col2, 
:old.col3, 
l_dml_type, 
sysdate 
); 
end; 
/
+0

+1 - Спасибо за это сообщение - я мог бы пойти в этом направлении, потому что он чист и прост –

+3

Могу ли я получить очки Джастина тогда ;-) – tbone

1

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

+1

Это похоже на комментарий и должно быть опубликовано как таковое в соответствии с вопрос. Вы должны участвовать больше в сообществе, чтобы получить некоторую репутацию, прежде чем у вас есть комментарии. Добро пожаловать в SO! – VKen

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