Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Wyrocznia SQL wielokrotnego wstawiania

EDYTUJ Dodano dwa przypadki testowe i możliwe obejście.

Chociaż Insert oświadczenie i insert all Instrukcja jest praktycznie tą samą konwencjonalną instrukcją INSERT. Ale jeśli chodzi o sekwencje, działają one inaczej.

Przypadek testowy 1:kolumny tożsamości

SQL> DROP TABLE table1 PURGE;

Table dropped.

SQL>
SQL> CREATE TABLE Table1 (
  2    Table1Id NUMBER GENERATED ALWAYS AS IDENTITY,
  3    column3 NUMBER,
  4    PRIMARY KEY (Table1Id)
  5  );

Table created.

SQL>
SQL> INSERT ALL
  2    INTO Table1 (column3) VALUES ('1')
  3    INTO Table1 (column3) VALUES ('2')
  4  SELECT * FROM dual;
INSERT ALL
*
ERROR at line 1:
ORA-00001: unique constraint (LALIT.SYS_C0010439) violated


SQL>

Zobaczmy, co tak naprawdę dzieje się pod maską -

SQL> CREATE TABLE Table1 ( 2 Table1Id NUMBER GENERATED ALWAYS AS IDENTITY, 3 column3 NUMBER, 4 CONSTRAINT A UNIQUE (Table1Id) 5 ); Table created. SQL> INSERT ALL 2 INTO Table1 (column3) VALUES (1) 3 INTO Table1 (column3) VALUES (2) 4 SELECT * FROM dual; INSERT ALL * ERROR at line 1: ORA-00001: unique constraint (LALIT.A) violated SQL> SELECT * FROM table1; no rows selected SQL> ALTER TABLE table1 2 DISABLE CONSTRAINT a; Table altered. SQL> INSERT ALL 2 INTO Table1 (column3) VALUES (1) 3 INTO Table1 (column3) VALUES (2) 4 SELECT * FROM dual; 2 rows created. SQL> SELECT * FROM table1; TABLE1ID COLUMN3 ---------- ---------- 2 1 2 2 SQL>

Tak więc sekwencja przeszła do nextval jednak, gdy po raz pierwszy wykonaliśmy Wstaw wszystko, wystąpiło naruszenie ograniczenia unikatowego. Następnie wyłączyliśmy ograniczenie niepowtarzalności , a kolejne polecenie Wstaw wszystko pokazuje, że sekwencja nie przeszła do nextval, a raczej próbowała wstawić zduplikowane klucze .

Chociaż problem nie występuje w przypadku INSERT-INTO-SELECT oświadczenie.

SQL> INSERT INTO table1(column3) SELECT LEVEL FROM dual CONNECT BY LEVEL <=5;

5 rows created.

SQL>
SQL> SELECT * FROM table1;

  TABLE1ID    COLUMN3
---------- ----------
         2          1
         3          2
         4          3
         5          4
         6          5

SQL>

Co zaskakujące, zgodnie z metadanymi sekwencja powinna automatycznie przechodzić do nextval, jednak nie dzieje się tak w przypadku instrukcji Insert All.

SQL> SELECT COLUMN_NAME,
  2    IDENTITY_COLUMN,
  3    DATA_DEFAULT
  4  FROM user_tab_cols
  5  WHERE table_name   ='TABLE1'
  6  AND IDENTITY_COLUMN='YES';

COLUMN_NAME     IDENTITY_COLUMN DATA_DEFAULT
--------------- --------------- ------------------------------
TABLE1ID        YES             "LALIT"."ISEQ$$_94458".nextval

SQL>

Przypadek testowy 2:jawne użycie sekwencji

WSTAW WSZYSTKO działałby w ten sam sposób, niezależnie od tego, czy używana jest kolumna tożsamości, czy wyraźna sekwencja jest używany.

SQL> DROP SEQUENCE s;

Sequence dropped.

SQL>
SQL> CREATE SEQUENCE s;

Sequence created.

SQL>
SQL> DROP TABLE t PURGE;

Table dropped.

SQL>
SQL> CREATE TABLE t (
  2    ID NUMBER,
  3    text VARCHAR2(50),
  4    CONSTRAINT id_pk PRIMARY KEY (ID)
  5  );

Table created.

SQL>
SQL> INSERT ALL
  2    INTO t VALUES (s.nextval, 'a')
  3    INTO t VALUES (s.nextval, 'b')
  4    INTO t VALUES (s.nextval, 'c')
  5    INTO t VALUES (s.nextval, 'd')
  6  SELECT * FROM dual;
INSERT ALL
*
ERROR at line 1:
ORA-00001: unique constraint (LALIT.ID_PK) violated


SQL>
SQL> SELECT * FROM T;

no rows selected

SQL>
SQL> ALTER TABLE t
  2    DISABLE CONSTRAINT id_pk;

Table altered.

SQL> INSERT ALL
  2    INTO t VALUES (s.nextval, 'a')
  3    INTO t VALUES (s.nextval, 'b')
  4    INTO t VALUES (s.nextval, 'c')
  5    INTO t VALUES (s.nextval, 'd')
  6  SELECT * FROM dual;

4 rows created.

SQL> SELECT * FROM T;

        ID TEXT
---------- ----------------------------------------
         2 a
         2 b
         2 c
         2 d

SQL>

Możliwe obejście — użycie wyzwalacza POZIOM WIERSZU

SQL> CREATE OR REPLACE TRIGGER t_trg
  2      BEFORE INSERT ON t
  3      FOR EACH ROW
  4      WHEN (new.id IS NULL)
  5      BEGIN
  6        SELECT s.NEXTVAL
  7        INTO   :new.id
  8        FROM   dual;
  9      END;
 10  /

Trigger created.

SQL> truncate table t;

Table truncated.

SQL> INSERT ALL
  2    INTO t (text) VALUES ('a')
  3    INTO t (text) VALUES ('b')
  4    INTO t (text) VALUES ('c')
  5    INTO t (text) VALUES ('d')
  6  SELECT * FROM dual;

4 rows created.

SQL> SELECT * FROM t;

        ID TEXT
---------- -------------------------
         3 a
         4 b
         5 c
         6 d

SQL>


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Groovy SQL Oracle Array Funkcja/procedura rejestracja parametrów wyjściowych

  2. Jak określić rozmiar tabel w Oracle?

  3. Jak przejść przez rozdzieloną listę w Oracle PLSQL?

  4. Oracle PL/SQL:Przykład DBMS_SCHEDULER.CREATE_JOB

  5. Oświadczenie FORALL z dolną i górną granicą w bazie danych Oracle