INSERT ALL с идентификатором с использованием DEFAULT ON NULL завершается с ошибкой PK Constraint - PullRequest
2 голосов
/ 19 сентября 2019

Используя Oracle 12, у меня есть определенная таблица, подобная этой:

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
)

Когда я делаю стандартные отдельные вставки строки и пропускаю идентификатор, вызывается 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 тогда ограничение Первичного ключа нарушается.

Мыможет переключиться обратно на стандартную пару триггер / последовательность, но надеялся получить дополнительную производительность от использования INSERT ALL.

Есть ли что-то особенное, что мне нужно сделать, чтобы эта массовая вставка работала на столе сключ, определенный с помощью DEFAULT ON NULL, или мне нужно вернуться к старой паре триггер / последовательность?

Ответы [ 2 ]

2 голосов
/ 19 сентября 2019

Это становится немного яснее, когда вы смотрите на план запроса:

-----------------------------------------------------------------------
| 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), назначая единственный идентификатор из последовательности и только после того, как он проходитрезультаты, вставив его в таблицы.Таким образом, этот подход не будет работать.

Вы можете попытаться использовать временную таблицу без идентификатора:

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 Loader.может работать так же.

2 голосов
/ 19 сентября 2019

Как насчет использования 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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...