首页 > 解决方案 > INSERT ALL 因触发器设置时间戳而失败

问题描述

假设我们有一个这样的表:

CREATE TABLE test_table 
(
    text   VARCHAR2(200) NOT NULL,
    text2  VARCHAR2(200) NOT NULL,
    ts     TIMESTAMP
);

我们想使用以下方法插入一些数据INSERT ALL

INSERT ALL 
    INTO test_table ( text, text2 ) VALUES ( 'test', 'test2' ) 
SELECT * FROM dual;

结果是

1 row inserted.

但是,当我们想添加触发器时,tsSYSTIMESTAMP

CREATE OR REPLACE TRIGGER  test_trigger
BEFORE INSERT ON  test_table
FOR EACH ROW
BEGIN
    DBMS_OUTPUT.put_line('text=' || :new.text);
    DBMS_OUTPUT.put_line('text2=' || :new.text2);
    DBMS_OUTPUT.put_line('ts=' || :new.ts);
    :new.ts := SYSTIMESTAMP;
END;
/

运行相同的脚本

SET SERVEROUT ON;
INSERT ALL 
    INTO test_table ( text, text2 ) VALUES ( 'test', 'test2' ) 
SELECT * FROM dual;

结果是:

text=test
text2=
ts=
INSERT ALL 
INTO test_table ( text, text2 ) VALUES ( 'test', 'test2' ) 
SELECT * FROM dual
Error report -
ORA-01400: cannot insert NULL into ("TEST"."TEST_TABLE"."TEXT2")

使用INSERT效果很好

SET SERVEROUT ON;
INSERT INTO test_table ( text, text2 ) VALUES ( 'test', 'test2' ) 

结果是

text=test
text2=test2
ts=
1 row inserted.

这也有效:

INSERT ALL 
INTO test_table ( text, text2, ts) VALUES ( 'test', 'test2', null ) 
SELECT * FROM dual

当我将ts列类型更改为DATE使用这种触发器时可以正常工作。我正在使用Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production,我也检查过Oracle 12c但没有错误,所以可能是 11g 版本中的某种错误?

标签: sqloracleoracle11g

解决方案


您的代码似乎没有问题,这可能是您使用的版本的错误。也就是说,您要实现的目标通常是通过以下 create table 语句来完成

CREATE TABLE test_table (
    text   VARCHAR2(200) NOT NULL,
    text2   VARCHAR2(200) NOT NULL,
    ts    TIMESTAMP not null default systimestamp
);

您根本不需要触发器。


推荐阅读