私はそのように定義されたOracleシーケンスを持っています:
CREATE SEQUENCE "DALLAS"."X_SEQ"
MINVALUE 0
MAXVALUE 999999999999999999999999999
INCREMENT BY 1 START WITH 0 NOCACHE NOORDER NOCYCLE ;
ストアドプロシージャでレコードを挿入するために使用されます。
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;
このプロシージャは、アプリケーションコードから実行するとエラーが返される場合があります。
ORA-01400: cannot insert NULL into ("DALLAS"."X"."THE_ID")
ORA-06512: at "DALLAS.X_PKG", line 40
ORA-06512: at line 1
関連するかどうかに関係なく詳細:
どのような状況でx_seq.nextval
nullになりますか?
私はこれがあなたのコードのアーチファクトになるか、あなたが使っている.netドライバになると確信しています。純粋なSQL-PL/SQLを使用して簡単なデモを作成しましたが、シーケンス値が失われることはありません。ちなみに、使用しているrefカーソルはおそらく不要であり、コードのパフォーマンスと可読性に影響を与える可能性があります-私のデモには、一貫して10%以上高速に実行するinsert_record2プロシージャが含まれています-私のラップトップでは約26秒で、refカーソルバージョンでは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;
テストケースを試してみてください。ダミーテーブルを作成し、データベースからのシーケンスを使用して100,000レコードを挿入します。問題ないと思います。次に、アプリケーションから同じものを挿入してみます。
これは、Oracleクライアントの不一致などの他の問題が原因である可能性がありますか?
問題を解決するが問題は解決しない別の解決策は、テーブルにトリガーを追加することです。
Dallas.Xのテーブルに挿入する前IF:the_idがnullである場合SELECT x_seq.nextval INTO:the_id FROM dual;終了IF;
私はまだコメントする特権を持っていないので、これを答えとして書きます:Oracleバージョン> = 11.1を使用しているため、SQLではなく PL/SQL式のシーケンス を使用できるので、これを試してください:
v_id := x_seq.nextval;
これの代わりに:
-- Get id value from sequence
SELECT x_seq.nextval
INTO v_id
FROM dual;
または、「。currval」を使用するときに疑問/落とし穴を聞いたことがありますが、v_idの個別の割り当てを省略して、このコードのみを使用することはできますか?
-- Line below is X_PKG line 40
INSERT INTO X
(the_id,
name,
update_userid)
VALUES
(x_seq.nextval,
p_name,
p_userid);
-- Return new id
OPEN cur_out FOR
SELECT x_seq.currval the_id
FROM dual;
申し訳ありませんが、これを試すための11gインスタンスがありません。