it-swarm.com.de

Einfügen in Oracle und Abrufen der generierten Sequenz-ID

Ich habe eine Handvoll roher SQL-Abfragen für SQL Server, die SCOPE_IDENTITY verwenden, um die generierte ID für ein bestimmtes INSERT sofort abzurufen, nachdem INSERT alles in einer Ausführung vorkommt.

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

SELECT SCOPE_IDENTITY() BatchID;

Die Frage ist: 

Was ist der beste Weg, dies für eine Oracle-Datenbank zu tun?

Kann dies über Standard-SQL auf Oracle durchgeführt werden, oder muss ich dies ändern, um eine gespeicherte Prozedur zu verwenden und etwas Ähnliches in den Rumpf der gespeicherten Prozedur einzufügen? 

Wenn es sich um eine gespeicherte Prozedur handeln muss, dann handelt es sich um den de-facto-Standard für das Abrufen der zuletzt generierten Sequenznummer. Es ist zu beachten, dass es wahrscheinlich zu überlappenden Ausführungen in mehreren Threads kommt nicht unbedingt die absolut zuletzt erzeugte ID. 

Wenn zwei gleichzeitig ausgeführt werden, muss jeder die korrekte generierte ID von jedem Anruf zurückgeben. Beachten Sie, dass ich aufgrund der Multithreading-Natur der Aufrufe nicht das @ @ IDENTITY von SQL Server verwende.

Ich würde es lieber als Roh-SQL beibehalten, da dies für mich viel einfacher ist, plattformübergreifend zu verwalten (einzelne Datei, die den SQL-Block jeder Plattform enthält, der durch DBMS-Identifizierungs-Tags getrennt ist). Gespeicherte Procs sind etwas mehr Arbeit für mich, aber ich kann diesen Weg gehen, wenn es der einzige Weg ist.

26
Allbite

Wenn Sie die Antworten von @Guru und @Ronnis ein wenig erweitern, können Sie die Sequenz ausblenden und sie mit Hilfe eines Triggers eher wie ein automatisches Inkrement aussehen lassen. Außerdem haben Sie eine Prozedur, die das Einfügen für Sie übernimmt und die generierte ID als Out zurückgibt Parameter.

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;
/

Sie können die Prozedur dann aufrufen, anstatt ein einfaches Einfügen durchzuführen, z. aus einem anoymous block:

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

Sie können den Anruf ohne explizite anonyme Blockierung durchführen, z. von SQL * Plus:

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

... und verwenden Sie die Bind-Variable :l_batchid, um anschließend auf den generierten Wert zu verweisen:

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

In Oracle gibt es für eine Spalte keine Funktionen zum automatischen Inkrementieren. Sie müssen ein SEQUENCE-Objekt erstellen. Sie können die Reihenfolge wie folgt verwenden:

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

... um die nächste Nummer zurückzugeben. Um die zuletzt erstellte Sequenz Nr. (In Ihrer Sitzung) herauszufinden, verwenden Sie:

my_sequence.currval

Diese Seite enthält mehrere vollständige Beispiele zur Verwendung von Sequenzen.

20
Ronnis

Das Speichern als gespeicherte Prozedur hat viele Vorteile. Sie können die Sequenz, die in die Tabelle eingefügt wird, mit der Syntax insert into table_name values returning abrufen.

Mögen:

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;
/

Oder einfach some_seq_val zurückgeben. Falls Sie SEQUENCE nicht verwenden und die Reihenfolge bei einer Berechnung eintreffen, können Sie returning into effektiv verwenden.

11
Guru

Sie können die unten stehende Anweisung verwenden, um die eingefügte Id zu einer Variablen-ähnlichen Sache zu bekommen.

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

Jetzt können Sie den Wert mit der folgenden Anweisung abrufen

SELECT :Inserted_Value FROM DUAL;
8
Sarath Avanavu

Sie können dies mit einer einzigen Anweisung tun - vorausgesetzt, Sie rufen sie von einem JDBC-artigen Connector mit In/Out-Parameterfunktionalität auf:

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

oder als pl-sql-Skript:

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