web-dev-qa-db-ja.com

Oracleへの挿入と生成されたシーケンスIDの取得

SQL Server用の生のSQLクエリがいくつかあります。これらのクエリは、SCOPE_IDENTITYを使用して、INSERTがすべて1回の実行で発生した直後に特定のINSERTに対して生成されたIDを取得します。

INSERT into Batch(
BatchName,
BatchType,
Source,
Area
) Values (
@strBatchName,
@strType,
@strSource,
@intArea
);

SELECT SCOPE_IDENTITY() BatchID;

質問は:

Oracleデータベースに対してこれを行う最良の方法は何ですか?

これは、標準SQLを介してOracleで実行できますか、またはストアドプロシージャを使用し、ストアドプロシージャの本体に同様のものを配置するように切り替える必要がありますか?

ストアドプロシージャである必要がある場合、最後に生成されたシーケンス番号を取得するための事実上の標準的な方法は、複数のスレッドで実行が重複する可能性が高いため、このメカニズムは正しい生成されたIDを取得する必要があることを考慮してください必ずしも最後に生成された絶対IDではありません。

2つが同時に実行される場合、それぞれがそれぞれの呼び出しから正しい生成されたIDを返す必要があります。呼び出しのマルチスレッドの性質のため、私はSQL Serverの「@@ IDENTITY」を使用していないことに注意してください。

プラットフォーム間(DBMS識別タグで区切られた各プラットフォームのSQLブロックを含む単一のファイル)で管理する方がはるかに簡単なので、可能であれば生のSQLとして保存する方がいいでしょう。ストアドプロシージャの管理はもう少し手間がかかりますが、それが唯一の方法であれば、その方法を使用できます。

27
Allbite

@Guruと@Ronnisからの回答を少し広げて、シーケンスを非表示にし、トリガーを使用して自動インクリメントのように見せることができます。パラメータ。

create table batch(batchid number,
    batchname varchar2(30),
    batchtype char(1),
    source char(1),
    intarea number)
/

create sequence batch_seq start with 1
/

create trigger batch_bi
before insert on batch
for each row
begin
    select batch_seq.nextval into :new.batchid from dual;
end;
/

create procedure insert_batch(v_batchname batch.batchname%TYPE,
    v_batchtype batch.batchtype%TYPE,
    v_source batch.source%TYPE,
    v_intarea batch.intarea%TYPE,
    v_batchid out batch.batchid%TYPE)
as
begin
    insert into batch(batchname, batchtype, source, intarea)
    values(v_batchname, v_batchtype, v_source, v_intarea)
    returning batchid into v_batchid;
end;
/

その後、単純な挿入を行う代わりに、プロシージャを呼び出すことができます。異常なブロックから:

declare
    l_batchid batch.batchid%TYPE;
begin
    insert_batch(v_batchname => 'Batch 1',
        v_batchtype => 'A',
        v_source => 'Z',
        v_intarea => 1,
        v_batchid => l_batchid);
    dbms_output.put_line('Generated id: ' || l_batchid);

    insert_batch(v_batchname => 'Batch 99',
        v_batchtype => 'B',
        v_source => 'Y',
        v_intarea => 9,
        v_batchid => l_batchid);
    dbms_output.put_line('Generated id: ' || l_batchid);
end;
/

Generated id: 1
Generated id: 2

明示的な匿名ブロックなしで呼び出しを行うことができます。 SQL * Plusから:

variable l_batchid number;
exec insert_batch('Batch 21', 'C', 'X', 7, :l_batchid);

...バインド変数:l_batchidを使用して、後で生成された値を参照します。

print l_batchid;
insert into some_table values(:l_batch_id, ...);
32
Alex Poole

列には、Oracleの自動インクリメント機能はありません。 SEQUENCEオブジェクトを作成する必要があります。次のようなシーケンスを使用できます。

insert into table(batch_id, ...) values(my_sequence.nextval, ...)

...次の番号を返します。 (セッションで)最後に作成されたシーケンスnrを見つけるには、次を使用します。

my_sequence.currval

このサイト には、シーケンスの使用方法に関するいくつかの完全な例があります。

20
Ronnis

ストアドプロシージャとして実行すると、多くの利点があります。構文insert into table_name values returningを使用して、テーブルに挿入されたシーケンスを取得できます。

のような:

declare
some_seq_val  number;
lv_seq        number;
begin
some_seq_val := your_seq.nextval;
insert into your_tab (col1, col2, col3) 
values (some_seq_val, val2, val3) returning some_seq_val into lv_seq;

dbms_output.put_line('The inserted sequence is: '||to_char(lv_seq));
end;
/

または、単にsome_seq_valを返します。 SEQUENCEを使用せず、何らかの計算でシーケンスに到達する場合は、returning intoを効果的に使用できます。

12
Guru

以下のステートメントを使用して、挿入されたIDを変数のようなものに取得できます。

INSERT INTO  YOUR_TABLE(ID) VALUES ('10') returning ID into :Inserted_Value;

これで、以下のステートメントを使用して値を取得できます

SELECT :Inserted_Value FROM DUAL;
8
Sarath Avanavu

単一のステートメントでこれを行うことができます-入力/出力パラメーター機能を備えたJDBCのようなコネクターから呼び出す場合を想定します。

insert into batch(batchid, batchname) 
values (batch_seq.nextval, 'new batch')
returning batchid into :l_batchid;

または、pl-sqlスクリプトとして:

variable l_batchid number;

insert into batch(batchid, batchname) 
values (batch_seq.nextval, 'new batch')
returning batchid into :l_batchid;

select :l_batchid from dual;
1
Franjo Markovic