Oracle view не обновляется, совет по триггерам вместо - PullRequest
2 голосов
/ 10 марта 2011

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

Чтобы поддерживать прямую совместимость с интерфейсными системами (т. Е. Нужно только изменить ссылку на базу данных), было создано представление, в котором отображаются те же столбцы, что и в старой таблице. Однако некоторые из этих столбцов только эмулируются, поэтому представление содержит конструкции, подобные этим:

(...)
CREATE OR REPLACE VIEW STAFF_DATA_COMPAT AS
SELECT
  NVL(knownas_surname,surname) as surname,
  first_name
  middle_name as mid-name
  NULL as ni,
  NULL as home_tel_no,
(...)

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

Я понимаю, что вам нужны триггеры INSTEAD OF для всех операторов DML (вставка, обновление, удаление). Я вижу, что триггер INSTEAD OF INSERT должен быть достаточно простым (просто вставьте поле NEW.field в реальную таблицу, где это уместно, и игнорируя остальные).

Но на самом деле вопрос: Как написать соответствующие триггеры INSTEAD OF UPDATE / DELETE? Например, как мне принять предложение WHERE исходного оператора DELETE? Есть ли что-то еще, о чем я должен беспокоиться, есть ли побочные эффекты при использовании этих триггеров?

Btw. Это Oracle 11g.

Ответы [ 2 ]

7 голосов
/ 10 марта 2011

Триггер INSTEAD OF будет выглядеть следующим образом (я предположил, что у вас есть столбец первичного ключа id):

SQL> CREATE OR REPLACE TRIGGER trg_staff_data_cpt_instead_upd
  2     INSTEAD OF UPDATE ON staff_data_compat
  3     FOR EACH ROW
  4  BEGIN
  5     UPDATE staff_data_compat_t
  6        SET knownas_surname = :new.surname,
  7            first_name = :new.first_name,
  8            middle_name = :new.mid_name
  9      WHERE id = :new.id
 10  END;
 11  /

Trigger created

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

SQL> CREATE TABLE staff_data_compat_t AS
  2  SELECT object_name knownas_surname,
  3         owner surname,
  4         object_type first_name,
  5         subobject_name middle_name
  6    FROM all_objects;

Table created

SQL> CREATE OR REPLACE VIEW staff_data_compat AS
  2  SELECT
  3    NVL(knownas_surname,surname) as surname,
  4    first_name,
  5    middle_name mid_name,
  6    NULL as ni,
  7    NULL as home_tel_no
  8  FROM staff_data_compat_t;

Представление создано

SQL> SELECT * FROM all_updatable_columns WHERE table_name = 'STAFF_DATA_COMPAT';

OWNER  TABLE_NAME         COLUMN_NAME  UPDATABLE INSERTABLE DELETABLE
------ ------------------ ------------ --------- ---------- ---------
VNZ    STAFF_DATA_COMPAT  SURNAME      NO        NO         NO
VNZ    STAFF_DATA_COMPAT  FIRST_NAME   YES       YES        YES
VNZ    STAFF_DATA_COMPAT  MID_NAME     YES       YES        YES
VNZ    STAFF_DATA_COMPAT  NI           NO        NO         NO
VNZ    STAFF_DATA_COMPAT  HOME_TEL_NO  NO        NO         NO

Если вам нужно только вставить / обновить эти столбцы, вы нене нужен триггер ВМЕСТО.

5 голосов
/ 10 марта 2011

Триггеры INSTEAD OF неявно "FOR EACH ROW", поэтому вам не нужно узнавать предложение WHERE, вы просто делаете что-то вроде этого:

begin
    delete base_table
    where pk = :old.pk;
end;

Здесь также показан один из недостатков триггеров INSTEAD OF: они работают построчно, а не в наборах.

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