W Oracle jak zapisać sekwencję.nazwa w zmiennej, która ma być ponownie użyta w wielu wstawkach?

13

Piszę skrypt wypełniający niektóre tabele danymi do testowania.

Chciałbym napisać coś takiego, ale nie wiem, jak to zrobić (jestem 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);

Wiem, że mógłbym zmienić kolejność zapytań i użyć sequence.currvalodwołania, ale wolałbym, aby identyfikator był zapisany w odpowiednio nazwanych zmiennych.

Może powinienem po prostu owinąć skrypt, DECLARE ... BEGIN ... END;ale mam nadzieję, że jest bardziej zwięzły sposób na zrobienie tego.


Dodatek 27 maja 2011 15:31

Wygląda na to, że w każdym razie muszę zadeklarować zmienne w DECLAREbloku. Więc próbuję z

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

ale pojawia się następujący błąd

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

Wskazuje to na deklarację zmiennej.

Korzystam z java, aby załadować skrypt z pliku i uruchomić go za pomocą sterownika Oracle JDBC (ojdbc14-10.2.0.4.0.jar) na serwerze Oracle 11g.

Tabela TEST_USER została utworzona za pomocą

create table TEST_USERS (
    id number(10, 0) not null,
    name varchar2(100),
    date_ins date default sysdate,
    primary key (id)
);
bazylika
źródło

Odpowiedzi:

11

Myślę, że tak to wygląda

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
źródło
10

Zrobiłbyś to z klauzulą RETURNING w pierwszym INSERTwyciągu.

AKTUALIZACJA: Zdarzyło mi się ostatnio pisać o tym na moim blogu .

Gajusz
źródło
8

Będziesz potrzebował bloku, jeśli deklarujesz zmienne

W wersji 11g poprawiono obsługę sekwencji, dzięki czemu można ich używać w następujący sposób:

ENABLED_USER_ID := SEQ.NEXTVAL;

zamiast używać selectinstrukcji (chociaż oba będą działać)

Inne opcje utrwalania wartości obejmują zapisywanie ich w tabeli lub tworzenie kontekstu , ale myślę, że sequence.currvalto naprawdę „właściwa odpowiedź” tutaj

Jack mówi, że spróbuj topanswers.xyz
źródło
7
SELECT seq.nextval 
   INTO ENABLED_USER_ID
FROM dual;
koń bez imienia
źródło
ENABLED_USER_ID powinien przejść w zadeklarowanym bloku, prawda?
basilikode
@ Xan: tak, zmienne można zdefiniować tylko w sekcji DECLARE, która z kolei jest poprawna tylko wtedy, gdy masz blok PL / SQL
a_horse_w_nazwie
4

Myślę, że możesz uciec bez żadnych dodatkowych zmiennych, używając 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
źródło