假设您在MY_CUSTOMER_TABLE
上有一个触发器,并且它有一个声明类型为MY_CUSTOMER_TABLE%ROWTYPE
的变量。如何将OLD
值分配给该变量?
CREATE TRIGGER CUSTOMER_BEFORE
BEFORE UPDATE ON MY_CUSTOMER_TABLE
FOR EACH ROW
DECLARE
old_version MY_CUSTOMER_TABLE%ROWTYPE;
BEGIN
old_version := :OLD; /* Causes a PLS-00049 bad bind variable 'OLD' */
old_version := OLD; /* Causes a PLS-00201 identifier 'OLD' must be declared */
END;
修改:
为了澄清,这是因为我使用触发器将MY_CUSTOMER_TABLE
中的行归档到MY_CUSTOMER_TABLE_HISTORY
。根据正在执行的操作(INSERT
,UPDATE
,DELETE
),我需要OLD
或NEW
中的所有字段:
CREATE TRIGGER CUSTOMER_BEFORE
BEFORE UPDATE ON MY_CUSTOMER_TABLE
FOR EACH ROW
DECLARE
historical_record MY_CUSTOMER_TABLE_HISTORY%ROWTYPE;
PROCEDURE
copy
(
source_record MY_CUSTOMER_TABLE%ROWTYPE,
destination_record IN OUT MY_CUSTOMER_TABLE_HISTORY%ROWTYPE
)
BEGIN
destination_record.customer_id := source_record.customer_id;
destination_record.first_name := source_record.first_name;
destination_record.last_name := source_record.last_name;
destination_record.date_of_birth := source_record.date_of_birth;
END;
BEGIN
/* I didn't want to replicate the same assignment statements for
each of the two cases: */
CASE
WHEN INSERT OR UPDATING THEN
copy( source_record => :NEW, destination_record => historical_record );
WHEN DELETING THEN
copy( source_record => :OLD, destination_record => historical_record );
END CASE;
/* Some other assignments to historical_record fields... */
INSERT INTO MY_CUSTOMER_TABLE_HISTORY VALUES historical_record;
END;
在这种情况下,PL / SQL不允许我将:OLD
或:NEW
传递给期望MY_CUSTOMER_TABLE%ROWTYPE
参数的过程。
答案 0 :(得分:4)
你做不到。 引用所有列(如SELECT *)通常是不好的做法,您应该指定所需的列。
答案 1 :(得分:2)
在文档中,您会发现:old和:new是列值,而不是行类型。因此,您必须手动构建行类型。
trigger ....
l_row mytable%rowtype;
begin
l_row.column1 := :old.column1;
l_row.column2 := :old.column2;
...
archive_function(l_row);
end;
答案 2 :(得分:1)
从我可以确定的内容的定义:NEW和:OLD确实有点模糊。我看到它被称为对“伪记录”的引用。看起来,不是实际的rowtype,而是每个列都可以在rowtype中引用,Oracle会为每个单独的列设置一个引用,然后使用:NEW和:OLD引用它。但是,正如你所发现的那样:新的和:OLD似乎不能自己引用。
例如,here。 (是的,我知道,这是一个Java参考,但请参阅以下评论:OLD本身不是一个有效的参考。
我还发现这个注释SYS.DBMS_DEBUG
包暗示:NEW /:OLD也不是有效的绑定。
- get_value和set_value现在支持绑定名称。绑定名称必须是 - 加上报价和大写。注意触发器绑定有 - 限定名称,即“:NEW”不是有效绑定,而“:NEW.CLMN” - 有效。
this 建议您使用AFTER
触发器吗?从您的示例来看,似乎没有对值进行任何验证(为了简单起见,您可能没有将它放到您的示例中)。
我试图设想一种方法来动态构建一个公共类型(在你的触发器中),使用all_tab_columns视图匹配你的表行类型,然后将所有值填入其中,但是不能完全包裹我的围绕可能会如何摆脱的细节...如果它甚至可以工作。它最终可能比记录历史记录所需的工作更多!