sql >> Databasteknik >  >> RDS >> Oracle

Flera infoga SQL-oracle

REDIGERA Lade till två testfall och en möjlig lösning.

Även om Insert uttalande och insert all uttalande är praktiskt taget samma konventionella infoga uttalande. Men när det kommer till sekvenser fungerar de annorlunda.

Testfall 1 :Identitetskolumner

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>

Låt oss se vad som faktiskt händer under huven -

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>

Så sekvensen gick vidare till nextval Men det var en unik överträdelse av begränsningen första gången vi gjorde en Infoga alla. Därefter inaktiverade vi den unika begränsningen , och den efterföljande Infoga alla avslöjar att sekvensen inte gick vidare till nästa val, snarare försökte den infoga dubbletter av nycklar .

Även om problemet inte uppstår med en INSERT-INTO-SELECT uttalande.

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>

Överraskande nog, enligt metadata, är sekvensen tänkt att fortsätta till nästa val automatiskt, men det händer inte med en Infoga alla-sats.

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>

Testfall 2 :Använd en sekvens explicit

INSERT ALLA skulle fungera på samma sätt oavsett om en identitetskolumn används eller en explicit sekvens används.

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>

Möjlig lösning – Använda en ROW LEVEL-utlösare

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. mysql - hur många kolumner är för många?

  2. Få namnet på den aktuella funktionen inuti funktionen med plpgsql

  3. Exklusive tabeller som inte stöds som ska fångas av Oracle Streams

  4. Kan inte hitta microsoft.sqlserver.batchparser.dll