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 加载程序加载它们这样简单的事情也可以。
使用 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 加载程序加载它们这样简单的事情也可以。