No Oracle, como salvo um sequence.nextval em uma variável para ser reutilizado em várias inserções?

13

Estou escrevendo um script para preencher algumas tabelas com dados para teste.

Gostaria de escrever algo como o seguinte, mas não sei como fazê-lo (sou Oracle 11g)

SET ENABLED_USER_ID = SEQ.NEXTVAL; // PSEUDOCODE
SET DISABLED_USER_ID = SEQ.NEXTVAL; // PSEUDOCODE

INSERT INTO USERS
        (ID,      USR_NAME)
VALUES  (:ENABLED_USER_ID, 'ANDREW');
INSERT INTO CAR
       (CAR_ID,         CAR_NAME, USR_ID)
VALUES (CARSEQ.NEXTVAL, 'FORD',   :ENABLED_USER_ID);

INSERT INTO USERS
        (ID,      USR_NAME)
VALUES  (:DISABLED_USER_ID, 'ANDREW');
INSERT INTO CAR
       (CAR_ID,         CAR_NAME, USR_ID)
VALUES (CARSEQ.NEXTVAL, 'FORD',   :DISABLED_USER_ID);

Eu sei que poderia reorganizar as consultas e usar a sequence.currvalreferência, mas eu preferiria ter o ID salvo em variáveis ​​nomeadas corretamente.

Talvez eu deva apenas envolver o script de uma forma, DECLARE ... BEGIN ... END;mas espero que exista uma maneira mais concisa de fazê-lo.


Adição 27 maio 2011 15:31

Parece que, em qualquer caso, eu tenho que declarar as variáveis ​​em um DECLAREbloco. Então, eu estou tentando com

DECLARE
  USER_ID NUMBER(10,0) := 1;
BEGIN   
  insert into TEST_USER
  values (user_id, 'andrew', sysdate);   
END;

mas eu recebo o seguinte erro

Caused by: java.sql.SQLException: ORA-06550: **line 2, column 27:**
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:

  * & = - + ; < / > at in is mod remainder not rem
  <an exponent (**)> <> or != or ~= >= <= <> and or like like2
  like4 likec between || multiset member submultiset

Isso aponta para a declaração da variável.

Estou usando o java para carregar o script de um arquivo e executando-o usando o driver Oracle JDBC (ojdbc14-10.2.0.4.0.jar) em um servidor Oracle 11g.

A tabela TEST_USER foi criada com

create table TEST_USERS (
    id number(10, 0) not null,
    name varchar2(100),
    date_ins date default sysdate,
    primary key (id)
);
basilikode
fonte

Respostas:

11

Eu acho que é assim

DECLARE
    ENABLED_USER_ID PLS_INTEGER;
    DISABLED_USER_ID PLS_INTEGER;
BEGIN
    ENABLED_USER_ID := SEQ.NEXTVAL;
    DISABLED_USER_ID := SEQ.NEXTVAL;

    INSERT INTO USERS (ID, USR_NAME)
    VALUES  (ENABLED_USER_ID, 'ANDREW');

    INSERT INTO CAR (CAR_ID, CAR_NAME, USR_ID)
    VALUES (CARSEQ.NEXTVAL, 'FORD', ENABLED_USER_ID);

    INSERT INTO USERS (ID, USR_NAME)
    VALUES  (DISABLED_USER_ID, 'ANDREW');

    INSERT INTO CAR (CAR_ID, CAR_NAME, USR_ID)
    VALUES (CARSEQ.NEXTVAL, 'FORD', DISABLED_USER_ID);
END;
/
bernd_k
fonte
10

Você faria isso com a cláusula RETURNING em sua primeira INSERTdeclaração.

UPDATE: Recentemente escrevi sobre isso em meu blog .

Gaius
fonte
8

Você precisará de um bloco se estiver declarando variáveis

Com o 11g, o suporte para sequências foi aprimorado para que você possa usá-las como:

ENABLED_USER_ID := SEQ.NEXTVAL;

em vez de usar uma selectdeclaração (embora ambos funcionem)

Outras opções para persistir os valores incluem salvá-los em uma tabela ou criar um contexto , mas acho que sequence.currvalé realmente a 'resposta certa' aqui

Jack diz que tenta topanswers.xyz
fonte
7
SELECT seq.nextval 
   INTO ENABLED_USER_ID
FROM dual;
um cavalo sem nome
fonte
ENABLED_USER_ID deve entrar em um bloco de declaração, certo?
basilikode 27/05
@Xan: sim, as variáveis só podem ser definidos em uma seção DECLARE que por sua vez só é válida se você tem um bloco PL / SQL
a_horse_with_no_name
4

Eu acho que você pode realmente fugir sem nenhuma variável extra usando currval:

INSERT INTO USERS
    (ID,      USR_NAME)
VALUES  (SEQ.NEXTVAL, 'ANDREW');
INSERT INTO CAR
   (CAR_ID,         CAR_NAME, USR_ID)
VALUES (CARSEQ.NEXTVAL, 'FORD',   SEQ.CURRVAL);
mustaccio
fonte