sql >> データベース >  >> RDS >> Oracle

複数挿入SQLOracle

    編集 2つのテストケースと可能な回避策を追加しました。

    Insert ステートメントとinsert all ステートメントは、実質的に同じ従来の挿入ステートメントです。ただし、シーケンスに関しては、動作が異なります。

    テストケース1:ID列

    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>
    

    内部で実際に何が起こっているか見てみましょう-

    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>
    

    したがって、シーケンスはnextvalに進みました。 ただし、最初に[すべて挿入]を実行したときに、固有の制約違反がありました。次に、一意性制約を無効にしました 、および後続の[すべて挿入]は、シーケンスがnextvalに進まなかったことを示しています。むしろ、重複キーを挿入しようとしました。 。

    INSERT-INTO-SELECTでは問題は発生しませんが ステートメント。

    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>
    

    驚いたことに、メタデータに従って、シーケンスは自動的にnextvalに進むことになっていますが、InsertAllステートメントでは発生しません。

    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>
    

    テストケース2:シーケンスを明示的に使用する

    すべて挿入 ID列が使用されている場合でも、明示的なシーケンスが使用されている場合でも、同じように機能します。 使用されます。

    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>
    

    考えられる回避策-ROWLEVELトリガーを使用する

    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で行ジェネレータを作成するにはどうすればよいですか?

    2. PostgreSQL 13:制限…タイ付き

    3. SQLServerのテーブルにJSONを挿入する方法

    4. SQLServerの論理AND演算子とは-SQLServer/TSQLチュートリアルパート120