INSERT ALL with ID using DEFAULT ON NULL 失败 PK 约束

INSERT ALL with ID using DEFAULT ON NULL fails PK Constraint

使用 Oracle 12,我有一个 table 定义类似于:

CREATE TABLE example 
(   "ID" NUMBER(*,0) DEFAULT ON NULL ex_seq.nextval NOT NULL ENABLE, 
    "SIG_BOOK" NUMBER(10,0), 
    "SIG_LINE" NUMBER(10,0), 
    "TRANSFER" NUMBER(10,0) DEFAULT NULL, 
     CONSTRAINT "PK_EXAMPLE_ID" PRIMARY KEY ("ID")
-- snipped
)

当我执行标准的单行插入并省略 ID 时,将调用 sequence.nextval 并正确插入该行。但是我们必须插入多达几千行,所以我尝试使用这样的代码:

INSERT ALL
  INTO example (sig_book, sig_line, transfer) VALUES (1,22000006,3436440)
  INTO example (sig_book, sig_line, transfer) VALUES (1,22000006,3184718)
SELECT * FROM dual

使用 INSERT ALL 时违反了主键约束。

我们可以切换回标准 Trigger/Sequence 对,但希望通过使用 INSERT ALL 获得额外的性能。

我是否需要做一些特别的事情才能让这个批量插入在使用 DEFAULT ON NULL 定义的密钥的 table 上工作,或者我是否需要 return旧 Trigger/Sequence 对?

使用 INSERT INTO . . . SELECT 怎么样?

INSERT INTO example (sig_book, sig_line, transfer) 
    SELECT 1,22000006,3436440 FROM DUAL UNION ALL
    SELECT 1,22000006,3184718 FROM DUAL;

当您查看查询计划时,它会变得更加清晰:

-----------------------------------------------------------------------
| Id  | Operation           | Name    | Rows  | Cost (%CPU)| Time     |
-----------------------------------------------------------------------
|   0 | INSERT STATEMENT    |         |     1 |     2   (0)| 00:00:01 |
|   1 |  MULTI-TABLE INSERT |         |       |            |          |
|   2 |   SEQUENCE          | EX_SEQ  |       |            |          |
|   3 |    FAST DUAL        |         |     1 |     2   (0)| 00:00:01 |
|   4 |   INTO              | EXAMPLE |       |            |          |
|   5 |   INTO              | EXAMPLE |       |            |          |
-----------------------------------------------------------------------

首先 Oracle 运行查询 (SELECT FROM dual),从序列中分配单个 id,只有在它遍历结果后,才将其插入到 tables。所以这个方法行不通。

您可以尝试使用不带 id 的临时 table:

CREATE TABLE example_without_id ("SIG_BOOK" NUMBER(10,0), ... );

INSERT ALL
  INTO example_without_id (sig_book, sig_line, transfer) VALUES (1,22000006,3436440)
  INTO example_without_id (sig_book, sig_line, transfer) VALUES (1,22000006,3184718)
SELECT * FROM dual;

INSERT INTO example (sig_book, sig_line, transfer) SELECT * FROM example_without_id;

将这些记录放入文件并通过 SQL 加载程序加载它们这样简单的事情也可以。