Триггер, который вставляет в таблицу dblink

#sql #triggers #oracle10g

#sql #триггеры #oracle10g

Вопрос:

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

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

    create or replace 
TRIGGER TRIGGER_FICHE 
AFTER INSERT ON T_AG 

BEGIN
  declare 
  begin


INSERT INTO t_ag_hab@DBLINK_DEV
()
values
();

/*commit;*/
end;
END;
  

Хранимая процедура, в которой будет вызван триггер (снова много параметров, не относящихся к их копированию :

 INSERT INTO T_AG()
       VALUES
                  ();


commit work;
  

Дело в том, что мы не можем выполнить фиксацию в триггере, я прочитал это и понимаю.

Но как я могу увидеть обновление моей таблицы с новым значением?

Когда процесс выполняется, ошибка nor отсутствует, но я не вижу новую строку в t_ag_hab.

Я знаю, что это не очень понятно, но я не знаю, как объяснить это по-другому. Как я могу это исправить?,

Комментарии:

1. Я пропустил важную часть: oracle 10g. Добавьте тег.

2. Следующее руководство предназначено для базы данных PostgreSQL, которая использует синтаксис PL / pgSQL Для запросов к базе данных и т.д. Синтаксис PL / pgSQL очень похож на синтаксис Oracle PL / SQL; поэтому вы можете найти эту ссылку полезной: postgresql.org/docs/9.3/interactive/plpgsql-trigger.html

3. Вы не увидите запись в удаленной таблице (или любой другой таблице) из другого сеанса, пока транзакция не будет зафиксирована, но вы должны иметь возможность видеть ее из той же транзакции. Вы говорите, что хотите, чтобы вставка удаленной таблицы была видна в другом месте до фиксации — что позволило бы ей сохраняться, даже если транзакция затем откатывается? За исключением некоторых случаев ведения журнала, это было бы странным требованием.

4. Нет, проблема не в этом. Дело в том, что когда триггер завершен, я не вижу новую строку в таблице. Слишком ясно, я выполняю вставку в хранимой процедуре, и после вставки (то есть после запуска) я делаю commit work , но ничего. На самом деле, я должен, commit work я должен сделать что-то вроде фиксации в dblink.

5. Ваш commit work зафиксирует данные как в локальной, так и в удаленной таблицах. Если ваши локальные данные видны после завершения транзакции, но удаленные данные отсутствуют, тогда происходит что-то еще — что-то удаляет их, или вы просматриваете версию удаленных данных, предварительно вставленную в другую транзакцию (она когда-нибудь появляется?). Или ваша ссылка вставляется не в удаленную базу данных, как вы думаете; вы выполняете запрос t_ag_ab@dblink_dev или запрашиваете из другой базы данных, и вы проверили определение ссылки DB и — если это уместно — tnsnames.ora используемый?

Ответ №1:

Поскольку вы вставляете в таблицу remove через ссылку на базу данных, у вас есть распределенная транзакция:

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

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

Двухфазный механизм фиксации прозрачен для пользователей, которые выполняют распределенные транзакции. Фактически, пользователям даже не нужно знать, что транзакция распределена. Оператор фиксации, обозначающий завершение транзакции, автоматически запускает механизм двухфазной фиксации. Для включения распределенных транзакций в тело приложения базы данных не требуется никакого кодирования или сложного синтаксиса оператора.

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

Один небольшой недостаток (хотя и особенность) ссылки на базу данных заключается в том, что он скрывает детали того, где выполняется работа. Вы можете удалить и воссоздать ссылку, чтобы ваш код обновлял другую целевую базу данных без необходимости изменять сам код. Но это означает, что ваш код не знает, куда на самом деле происходит вставка — вам нужно будет проверить словарь данных, чтобы увидеть, куда указывает ссылка. И даже тогда вы можете не знать, поскольку ссылка может использовать псевдоним TNS для идентификации базы данных, а изменения в tnsnames.ora не видны из базы данных.

Если вы можете видеть данные после фиксации с помощью запроса t_ag_ab@dblink_dev из той же базы данных, в которой вы запускали свою процедуру, но вы не можете видеть, указывает ли это при локальном запросе из базы данных, на которую вы ожидаете, что это будет указано, тогда ссылка указывает не туда, куда вы думаете. Вставка выполняется в одну базу данных, а вы выполняете свой запрос к другой. Однако только вы можете решить, какая база данных является «правильной»; и либо переопределите ссылку (или запись TNS, если это уместно), либо измените, где вы выполняете запрос.

Комментарии:

1. Спасибо за этот полный ответ. Как сказано в комментарии к вопросу, на самом деле, имя DBLINK, которое уже было создано, причинило мне вред в БД. Я вставлял в старую базу данных, в то время как DBLINK не был изменен.

Ответ №2:

Я не могу четко понять ваше требование. Для обновления записей в основной таблице и вставки старых записей в таблицу аудита. мы можем использовать приведенный ниже запрос в качестве триггера.(MS-SQL)

 Create trigger trg_update ON T_AGENT
AFTER UPDATE AS 
BEGIN

UPDATE Tab1
SET COL1 = I.COL1, COL2=I.COL2
FROM INSERTED I INNER JOIN Tab1 ON I.COL3=Tab1.Col3

INSERT Tab1_Audit(COL1,COL2,COL3)
SELECT Tab1 FROM DELETED

RETURN;
END;
  

Ответ №3:

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

 SQL> CREATE OR REPLACE TRIGGER validate_update
  2  AFTER INSERT OR UPDATE ON T_AGENT
  3  FOR EACH ROW
  4  BEGIN
  5    IF UPDATING('ACCOUNT_ID') THEN     -- do something like this when updating
  6      DBMS_OUTPUT.put_line ('ERROR');  -- add your action here
  7    ELSIF INSERTING THEN
  8      INSERT INTO t_ag_hab@DBLINK_DEV() values();
  9    END IF;
  10  END;
  11  /

  Trigger created.