Вставка в Oracle и получение сгенерированного идентификатора последовательности - PullRequest
27 голосов
/ 06 апреля 2011

У меня есть несколько необработанных запросов SQL для SQL Server, которые используют SCOPE_IDENTITY для извлечения сгенерированного идентификатора для определенного INSERT сразу после того, как этот INSERT происходит все в одном выполнении…

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

SELECT SCOPE_IDENTITY() BatchID;

Вопрос:1004 *

Каков наилучший способ сделать это для базы данных Oracle?

Можно ли это сделать в Oracle с помощью стандартного SQL или мне нужно переключить это, чтобы использовать хранимую процедуру и поместить что-то подобное втело хранимой процедуры?

Если это должен быть сохраненный процесс, то каков де-факто стандартный способ извлечения последнего сгенерированного порядкового номера, учитывая, что в нескольких потоках, вероятно, будут выполняться перекрывающиеся исполнения, поэтому этот механизм должен будетполучить правильный сгенерированный идентификатор и не обязательно абсолютный последний сгенерированный идентификатор.

Если два выполняются одновременно, то каждый должен возвращать правильный сгенерированный идентификатор из каждого соответствующего вызова.Обратите внимание, что я не использую «@@ IDENTITY» в SQL Server из-за многопоточного характера вызовов.

Я бы предпочел сохранить его как необработанный SQL, если это возможно, поскольку мне намного проще управлять на разных платформах (одинфайл, содержащий блок SQL каждой платформы, разделенный тегами идентификации СУБД).Хранимые процедуры - немного больше работы для меня, но я могу пойти по этому пути, если это единственный возможный способ.

Ответы [ 5 ]

31 голосов
/ 06 апреля 2011

Расширяя немного ответы от @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, ...);
20 голосов
/ 06 апреля 2011

В Oracle нет функций автоинкремента для столбца. Вам нужно создать объект SEQUENCE. Вы можете использовать последовательность как:

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

... чтобы вернуть следующий номер. Чтобы узнать последнюю созданную последовательность nr (в вашем сеансе), вы должны использовать:

my_sequence.currval

На этом сайте есть несколько полных примеров использования последовательностей.

12 голосов
/ 06 апреля 2011

Выполнение в виде хранимой процедуры имеет много преимуществ. Вы можете получить последовательность, вставленную в таблицу, используя синтаксис 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. Если вы не используете ПОСЛЕДОВАТЕЛЬНОСТЬ и прибываете в последовательность для некоторых вычислений, вы можете эффективно использовать returning into.

8 голосов
/ 21 января 2016

Вы можете использовать приведенный ниже оператор, чтобы получить вставленный идентификатор для объекта, похожего на переменную.

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

Теперь вы можете получить значение, используя приведенный ниже оператор

SELECT :Inserted_Value FROM DUAL;
1 голос
/ 25 января 2018

Вы можете сделать это с помощью одного оператора - при условии, что вы вызываете его из 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;
...