我们在 Oracle DB 版本 21.3 上发现了一个错误(同样也在 19.3 版本上进行了测试)。如果您在插入语句中使用函数并使用返回子句返回值,则结果是您在插入语句中调用的函数执行两次!!!
下面是一个使用为序列创建下一个值的函数的示例。我知道您可以直接使用“.nextval”(如图所示工作正常),但这只是演示函数双重执行的示例。我可以使用任何其他函数并且会被执行两次(例如计算某些东西)。
您可以使用此示例测试它的工作原理:
create sequence seq_1;
create sequence seq_2;
create table test1000 (id number, a varchar2(4004));
create table test1001 (id number, a varchar2(1001));
create or replace function testfun return number is
v_a number;
begin
select seq_1.nextval into v_a from dual;
dbms_output.put_line('FUNCTION RETURNS SEQ_1 VALUE: '||v_a);
return v_a;
end;
/
如果你执行这个,你可以测试这个:
declare
v_a varchar2(100);
begin
insert into test1000(id, a) values (seq_2.nextval, 'SEQ_1:'||testfun) returning a into v_a;
dbms_output.put_line(v_a);
insert into test1001(id, a) values (seq_2.nextval, 'SEQ_1:'||testfun) returning a into v_a;
dbms_output.put_line(v_a);
end;
/
它将输出:
FUNCTION RETURNS SEQ_1 VALUE: 1
SEQ_1:1
FUNCTION RETURNS SEQ_1 VALUE: 2
FUNCTION RETURNS SEQ_1 VALUE: 3
SEQ_1:3
您可以在第二次插入中看到双重执行。表 test1001 中的数据值为 2,但变量 v_a 中返回的值不同(值为 3)。在第一次插入中没有发生双重执行,而是在第二次中发生。我相信这是因为第二个表具有字段“a”,其中 varchar2 的最大大小高于 4000,我相信这与 oracle 如何处理扩展的 varchar2 类型(MAX_STRING_SIZE 在我们的数据库中扩展)有关。
我向 Oracle 报告了这个错误。当我收到他们的回复时,我会更新这个......