Создайте триггер после вставки, который обновит другую таблицу - PullRequest
1 голос
/ 08 мая 2020

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

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

Create or replace trigger trigger_healed 
After insert on swab_test
For each row
Begin
  if :new.result = 'Negative' then
     UPDATE illness_update
     SET illness_update.state = 'healed'
     WHERE illness_update.id_user = :new.id_user;
 end if;
end;

Это результат, который я пытаюсь получить.

SWAB_TEST

id_user id_swab swab_result   date
1       test1   'positive'  May-01-2020
1       test1   'negative'  May-08-2020
2       test2   'negative'  May-02-2020

ILLNESS_UPDATE

id_user  state     date
1       'healed'  May-08-2020

Ответы [ 2 ]

2 голосов
/ 08 мая 2020

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

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

create view illness_update_view(id_user, state, date) as
select id_user, 'healed', date
from (
    select 
        s.*, 
        lag(swab_result) over(partition by id_user order by date) lag_swab_result
    from swab_test s
) s
where lag_swab_result = 'positive' and swab_result = 'negative'

Представление использует оконную функцию lag() для восстановления "предыдущего" результата каждой строки (для каждого пользователя) . Строки, представляющие переходы от положительного результата к отрицательному, сохраняются.

1 голос
/ 09 мая 2020

Поскольку @GMB указывает, что вы не можете делать то, что просите, со стандартным триггером строки до / после, поскольку он не может ссылаться на swab_test, поскольку это таблица, вызывающая срабатывание триггера (что приведет к ошибке мутирующей таблицы ORA-04091 ). Но вы можете сделать это с помощью составного триггера (или оператора After). Но прежде чем перейти к этому, я думаю, что ваша модель данных имеет фатальный недостаток.

Вы установили возможность проведения множественных мазковых тестов. Логическим расширением этого является то, что каждый id_swab проверяет другое условие или другой тест на одно и то же условие. Однако тест (id_swab) отсутствует в таблице обновления вашей болезни. Это означает, что если какой-либо тест дает отрицательный результат после получения предыдущего положительного результата, пользователь исцеляется от ВСЕХ тестов. Чтобы исправить это, вам нужно включить id_swab id, чтобы определить исцеление. Поскольку GMB предлагает лучшее решение, я остановлюсь на нем подробнее. Сначала сбросьте таблицу Illness_update. Затем создайте Illness_update как представление. (ПРИМЕЧАНИЕ: в ответ на ваш вопрос вам НЕ нужен триггер для представления, все необходимое находится в swab_test; см. оконную функцию с задержкой .

create view illness_update(id_user, state, swab_date) as
select id_user,  id_swab, 'healed' state,swab_date
from (
    select 
        s.* 
     ,  lag(swab_result) over(partition by id_user, id_swab
                             order by id_user, id_swab, swab_date) as lag_swab_result
    from swab_test s 
) s
where lag_swab_result = 'positive'
  and swab_result = 'negative'; 

Теперь, как упоминалось выше , если ваше назначение требует использования триггера, см. fiddle . Примечание: Я не использую дату (или любой другой тип данных) в качестве имени столбца. Здесь я использую swab_date во всех экземпляры.

...