我有一个像这样定义的 Oracle 序列:
CREATE SEQUENCE "DALLAS"."X_SEQ"
MINVALUE 0
MAXVALUE 999999999999999999999999999
INCREMENT BY 1 START WITH 0 NOCACHE NOORDER NOCYCLE ;
Run Code Online (Sandbox Code Playgroud)
它在存储过程中用于插入记录:
PROCEDURE Insert_Record
(p_name IN VARCHAR2,
p_userid IN INTEGER,
cur_out OUT TYPES_PKG.RefCursor)
IS
v_id NUMBER := 0;
BEGIN
-- Get id value from sequence
SELECT x_seq.nextval
INTO v_id
FROM dual;
-- Line below is X_PKG line 40
INSERT INTO X
(the_id,
name,
update_userid)
VALUES
(v_id,
p_name,
p_userid);
-- Return new id
OPEN cur_out FOR
SELECT v_id the_id
FROM dual;
END;
Run Code Online (Sandbox Code Playgroud)
有时,此过程在从应用程序代码执行时会返回错误。
ORA-01400: cannot insert NULL into ("DALLAS"."X"."THE_ID")
ORA-06512: at "DALLAS.X_PKG", line 40
ORA-06512: at line 1
Run Code Online (Sandbox Code Playgroud)
可能相关或不相关的详细信息:
在什么情况下可以x_seq.nextval
为空?
我非常确定这最终将成为您的代码或您正在使用的 .net 驱动程序的产物。我已经使用纯 SQL - PL/SQL 为您制作了一个快速演示,并且永远不会丢失序列值。顺便说一句,您使用的引用光标可能是不必要的,并且可能会影响代码的性能和可读性 - 我的演示包括一个 insert_record2 过程,该过程始终快于 10% 以上 - 在我的笔记本电脑上大约需要 26 秒,而引用光标版本则需要 36 秒。至少我也认为更容易理解。显然,您可以针对带有审核触发器的测试数据库运行修改后的版本。
/*
demo for dbse
assumes a user with create table, create sequence, create procedure pivs and quota.
*/
drop table dbse13142 purge;
create table dbse13142(
the_id number not null
, name varchar2(20)
, userid number)
;
drop sequence x_seq;
CREATE SEQUENCE X_SEQ NOCACHE NOORDER NOCYCLE ;
create or replace PROCEDURE Insert_Record
(p_name IN VARCHAR2,
p_userid IN INTEGER,
cur_out OUT sys_refcursor)
IS
v_id NUMBER := 0;
BEGIN
-- Get id value from sequence
SELECT x_seq.nextval
INTO v_id
FROM dual;
-- Line below is X_PKG line 40
INSERT INTO dbse13142
(the_id,
name,
userid)
VALUES
(v_id,
p_name,
p_userid);
-- Return new id
OPEN cur_out FOR
SELECT v_id the_id
FROM dual;
END;
/
create or replace PROCEDURE Insert_Record2
(p_name IN VARCHAR2,
p_userid IN INTEGER,
p_theid OUT dbse13142.the_id%type)
IS
BEGIN
-- Get id value from sequence
SELECT x_seq.nextval
INTO p_theid
FROM dual;
-- Line below is X_PKG line 40
INSERT INTO dbse13142
(the_id,
name,
userid)
VALUES
(p_theid,
p_name,
p_userid);
END;
/
set timing on
declare
c sys_refcursor;
begin
for i in 1..100000 loop
insert_record('User '||i,i,c);
close c;
end loop;
commit;
end;
/
select count(*) from dbse13142;
truncate table dbse13142;
declare
x number;
begin
for i in 1..100000 loop
insert_record2('User '||i,i,x);
end loop;
commit;
end;
/
select count(*) from dbse13142;
truncate table dbse13142;
Run Code Online (Sandbox Code Playgroud)