如何创建将插入更新/插入时的旧值和新值的触发器

发布于 2025-02-09 08:46:22 字数 2002 浏览 5 评论 0原文

在过去的3个小时中,我在互联网上看了很多,但是我无法设法使扳机起作用。这是我的设置:

CREATE TABLE faktura ( 
                       extnr        VARCHAR2(32), 
                       fakturanr    NUMBER,
                       fakturadate  DATE, 
                       partner_name VARCHAR2(32)
                     )

INSERT INTO faktura(extnr, fakturanr, fakturadate, partner_name)
VALUES('1234/12', 1, to_date('01.01.2022', 'dd.mm.yyyy'), 'Global Sellers LTD');

INSERT INTO faktura(extnr, fakturanr, fakturadate, partner_name)
VALUES('111', 2, to_date('02.01.2022', 'dd.mm.yyyy'), 'Thomas Limited');

CREATE OR REPLACE VIEW view_faktura AS 
SELECT extnr, fakturanr, fakturadate 
  FROM faktura;

SELECT * 
  FROM faktura; 
  
SELECT * 
  FROM view_faktura;

有一个用户用户1仅在上授予 on view_faktura。在视图上进行更新语句将更改基础faktura表数据。

UPDATE sol.view_faktura 
   SET extnr = '21' 
 WHERE fakturanr = '2'

我想做的是登录另一个新表(或在底层表的基础表)上进行的任何更新:

CREATE TABLE log_table( 
                        id             NUMBER GENERATED BY DEFAULT AS IDENTITY, 
                        field changed?, 
                        old_value      VARCHAR2(50), 
                        new_value      VARCHAR2(50), 
                        fakturanr      NUMBER, 
                        date_of_change DATE
                       );

现在,我尝试触发器:

create or replace trigger ChangeOnFaktura
  after update of "some column" on faktura "(or view_faktura)"
  for each row
declare
begin
  insert into log_table (
    old_value, new_value, date_of_change, "field changed?", fakturanr
  ) values (
    oldvalue, newvalue, sysdate, "field changed?", "fakturanr from the changed record"
  );

有人可以帮助我吗?

编辑:将一些引号更改为“而不是'”。字段更改了吗

错误(2,98):PLS-00103:在期望以下一个时遇到符号“文件终止” :(如果loop mod mod mod mod null pragma提出返回返回返回retalle with&lt with&lt with< LT

I have looked a lot through the internet the past 3 hours but I cannot manage to make the trigger work. Here is my setup:

CREATE TABLE faktura ( 
                       extnr        VARCHAR2(32), 
                       fakturanr    NUMBER,
                       fakturadate  DATE, 
                       partner_name VARCHAR2(32)
                     )

INSERT INTO faktura(extnr, fakturanr, fakturadate, partner_name)
VALUES('1234/12', 1, to_date('01.01.2022', 'dd.mm.yyyy'), 'Global Sellers LTD');

INSERT INTO faktura(extnr, fakturanr, fakturadate, partner_name)
VALUES('111', 2, to_date('02.01.2022', 'dd.mm.yyyy'), 'Thomas Limited');

CREATE OR REPLACE VIEW view_faktura AS 
SELECT extnr, fakturanr, fakturadate 
  FROM faktura;

SELECT * 
  FROM faktura; 
  
SELECT * 
  FROM view_faktura;

There is a user USER1 that has granted UPDATE on view_faktura only. Making UPDATE statement on the view will change the underlying faktura table data.

UPDATE sol.view_faktura 
   SET extnr = '21' 
 WHERE fakturanr = '2'

What I want to do is log into another new table any UPDATEs that are done on the view (or underlying table):

CREATE TABLE log_table( 
                        id             NUMBER GENERATED BY DEFAULT AS IDENTITY, 
                        field changed?, 
                        old_value      VARCHAR2(50), 
                        new_value      VARCHAR2(50), 
                        fakturanr      NUMBER, 
                        date_of_change DATE
                       );

Now, I try the trigger:

create or replace trigger ChangeOnFaktura
  after update of "some column" on faktura "(or view_faktura)"
  for each row
declare
begin
  insert into log_table (
    old_value, new_value, date_of_change, "field changed?", fakturanr
  ) values (
    oldvalue, newvalue, sysdate, "field changed?", "fakturanr from the changed record"
  );

Can anyone help me with this?

Edit: Changed some quotation marks to " instead of '. "field changed?" I do not know how to refer to this.

Error I get (without any of the fields I do not know how to refer to in double quotations) is:

Error(2,98): PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: ( begin case declare end exception exit for goto if loop mod null pragma raise return select update while with << continue close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe purge

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

云淡月浅 2025-02-16 08:46:22

定义日志表以使field_changed具有数据类型和有效标识符:

CREATE TABLE log_table( 
  id             NUMBER GENERATED BY DEFAULT AS IDENTITY, 
  field_changed  VARCHAR2(30), 
  old_value      VARCHAR2(32), 
  new_value      VARCHAR2(32), 
  fakturanr      NUMBER,
  date_of_change DATE
);

然后您可以使用:new and :old 记录要获取值和end;语句终止块:

create or replace trigger ChangeOnFaktura
  after update of extnr on faktura
  for each row
DECLARE
BEGIN
  insert into log_table (
    old_value,
    new_value,
    date_of_change,
    field_changed,
    fakturanr
  ) values (
    :OLD.extnr,
    :NEW.extnr,
    SYSDATE,
    'EXTNR',
    :NEW.fakturanr
  );
END;
/

或,作为automous_transaction

create or replace trigger ChangeOnFaktura
  after update of extnr on faktura
  for each row
DECLARE
  PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
  insert into log_table (
    old_value,
    new_value,
    date_of_change,
    field_changed,
    fakturanr
  ) values (
    :OLD.extnr,
    :NEW.extnr,
    SYSDATE,
    'EXTNR',
    :NEW.fakturanr
  );
  COMMIT;
END;
/

然后,在更新后,日志表包含:

idfield_changedold_valuenew_valuefakturanrdate_of_change
1extnr1112122022-06-21 09:21:16

db&lt;&gt; gt; fiddle 此处


或对于多列,您可以创建触发器的第二份副本并更改列名或使用:

create or replace trigger ChangeOnFaktura
  after update on faktura
  for each row
BEGIN
  IF :OLD.extnr <> :NEW.extnr
  OR (:OLD.extnr IS NULL AND :NEW.extnr IS NOT NULL)
  OR (:OLD.extnr IS NOT NULL AND :NEW.extnr IS NULL)
  THEN
    insert into log_table (
      old_value,
      new_value,
      date_of_change,
      field_changed,
      fakturanr
    ) values (
      :OLD.extnr,
      :NEW.extnr,
      SYSDATE,
      'EXTNR',
      :NEW.fakturanr
    );
  END IF;
  
  IF :OLD.partner_name <> :NEW.partner_name
  OR (:OLD.partner_name IS NULL AND :NEW.partner_name IS NOT NULL)
  OR (:OLD.partner_name IS NOT NULL AND :NEW.partner_name IS NULL)
  THEN
    insert into log_table (
      old_value,
      new_value,
      date_of_change,
      field_changed,
      fakturanr
    ) values (
      :OLD.partner_name,
      :NEW.partner_name,
      SYSDATE,
      'PARTNER_NAME',
      :NEW.fakturanr
    );
  END IF;
END;
/

db&lt;&gt;&gt; fiddle 在这里

Define your log table so that field_changed has a data type and a valid identifier:

CREATE TABLE log_table( 
  id             NUMBER GENERATED BY DEFAULT AS IDENTITY, 
  field_changed  VARCHAR2(30), 
  old_value      VARCHAR2(32), 
  new_value      VARCHAR2(32), 
  fakturanr      NUMBER,
  date_of_change DATE
);

Then you can define the trigger, using the :NEW and :OLD records to get the values and an END; statement to terminate the block:

create or replace trigger ChangeOnFaktura
  after update of extnr on faktura
  for each row
DECLARE
BEGIN
  insert into log_table (
    old_value,
    new_value,
    date_of_change,
    field_changed,
    fakturanr
  ) values (
    :OLD.extnr,
    :NEW.extnr,
    SYSDATE,
    'EXTNR',
    :NEW.fakturanr
  );
END;
/

or, as an AUTONOMOUS_TRANSACTION:

create or replace trigger ChangeOnFaktura
  after update of extnr on faktura
  for each row
DECLARE
  PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
  insert into log_table (
    old_value,
    new_value,
    date_of_change,
    field_changed,
    fakturanr
  ) values (
    :OLD.extnr,
    :NEW.extnr,
    SYSDATE,
    'EXTNR',
    :NEW.fakturanr
  );
  COMMIT;
END;
/

Then, after the update, the log table contains:

IDFIELD_CHANGEDOLD_VALUENEW_VALUEFAKTURANRDATE_OF_CHANGE
1EXTNR1112122022-06-21 09:21:16

db<>fiddle here


Or for multiple columns, you can either create a second copy of the trigger and change the column names or use:

create or replace trigger ChangeOnFaktura
  after update on faktura
  for each row
BEGIN
  IF :OLD.extnr <> :NEW.extnr
  OR (:OLD.extnr IS NULL AND :NEW.extnr IS NOT NULL)
  OR (:OLD.extnr IS NOT NULL AND :NEW.extnr IS NULL)
  THEN
    insert into log_table (
      old_value,
      new_value,
      date_of_change,
      field_changed,
      fakturanr
    ) values (
      :OLD.extnr,
      :NEW.extnr,
      SYSDATE,
      'EXTNR',
      :NEW.fakturanr
    );
  END IF;
  
  IF :OLD.partner_name <> :NEW.partner_name
  OR (:OLD.partner_name IS NULL AND :NEW.partner_name IS NOT NULL)
  OR (:OLD.partner_name IS NOT NULL AND :NEW.partner_name IS NULL)
  THEN
    insert into log_table (
      old_value,
      new_value,
      date_of_change,
      field_changed,
      fakturanr
    ) values (
      :OLD.partner_name,
      :NEW.partner_name,
      SYSDATE,
      'PARTNER_NAME',
      :NEW.fakturanr
    );
  END IF;
END;
/

db<>fiddle here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文