Вставка нескольких строк в Oracle

В обсуждении о вставке нескольких строк в Oracle были продемонстрированы два подхода:

Сначала:

insert into pager (PAG_ID,PAG_PARENT,PAG_NAME,PAG_ACTIVE)
          select 8000,0,'Multi 8000',1 from dual
union all select 8001,0,'Multi 8001',1 from dual

Во-вторых:

INSERT ALL
   INTO t (col1, col2, col3) VALUES ('val1_1', 'val1_2', 'val1_3')
   INTO t (col1, col2, col3) VALUES ('val2_1', 'val2_2', 'val2_3')
   INTO t (col1, col2, col3) VALUES ('val3_1', 'val3_2', 'val3_3')
   .
   .
   .
SELECT 1 FROM DUAL;

Может ли кто-нибудь аргументировать предпочтение использования одного над другим?

P.S. Я сам не проводил никаких исследований (даже план объяснений), поэтому любая информация или мнение будут оценены.

Спасибо.

Ответ 1

С точки зрения производительности эти запросы идентичны.

UNION ALL не повредит производительность, поскольку Oracle оценивает запрос UNION 'ed только тогда, когда он ему нужен, он не кэширует результаты в первую очередь.

Синтаксис

SELECT более гибкий в этом смысле, что вы можете более легко получить запрос SELECT, если хотите что-то изменить.

Например, этот запрос:

insert into pager (PAG_ID,PAG_PARENT,PAG_NAME,PAG_ACTIVE)
          select 8000,0,'Multi 8000',1 from dual
union all select 8001,0,'Multi 8001',1 from dual

можно переписать как

INSERT
INTO    pager (PAG_ID,PAG_PARENT,PAG_NAME,PAG_ACTIVE)
SELECT  7999 + level, 0, 'Multi ' || 7999 + level, 1
FROM    dual
CONNECT BY
        level <= 2

Заменив 2 на соответствующее число, вы можете получить любое количество строк, которые вы хотите.

В случае INSERT ALL вам придется дублировать описание таблицы назначения, которое менее читаемо, если вам нужно, скажем, 40 rows.

Ответ 2

Я бы предположил, что решение 1 - это немного хак, который работает и, вероятно, менее эффективен, чем разработанная альтернатива Insert ALL.

Вставить все действительно предназначено для того, чтобы вы вставляли много строк в более чем 1 таблицу в результате выбора, например:

Insert ALL
into 
  t1 (c1, c2) values (q1, q2)
  t2 (x1, x2) values (q1, q3)
select q1, q2, q3 from t3 

Если вы хотите загрузить тысячи строк , а их нет в базе данных уже, я не думаю, что это лучший способ сделать это. Если ваши данные находятся в файле, вы хотите посмотреть внешние таблицы или загрузчик SQL, чтобы эффективно вставлять строки для вас.

Ответ 3

Метод INSERT ALL имеет проблему с вставкой большего количества строк в таблицу.

Недавно мне захотелось вставить 1130 строк в таблицу с одним оператором SQL. Когда я попытался сделать это с помощью метода INSERT ALL, я получил следующую ошибку:

ORA-24335 - не может поддерживать более 1000 столбцов

Когда я использовал подход INSERT INTO .. UNION ALL .., все шло хорошо.

Btw. Я не знал о методе UNION ALL, прежде чем нашел это обсуждение:)

Ответ 4

Утверждение, использующее UNION ALL, теоретически представляет собой небольшой недостаток производительности, поскольку он должен объединять результаты всех операторов до того, как вставка может произойти. INSERT ALL не имеет этого недостатка, поскольку конечный результат уже может обрабатываться по очереди.

Но практически оптимизатор внутри Oracle должен сделать разницу незначительной, и это зависит от ваших предпочтений, которые вы выбираете.

По моему мнению, INSERT ALL является лучшим для человека, читаемым для двух, в то время как вариант UNION ALL - это тот, который занимает меньше места, когда такая вставка автоматически генерируется.

Ответ 5

Я пробовал некоторые тесты, и более быстрое решение должно быть

insert into pager (PAG_ID,PAG_PARENT,PAG_NAME,PAG_ACTIVE)
          select 8000,0,'Multi 8000',1 from dual
union all select 8001,0,'Multi 8001',1 from dual

буферизация между 300 ↔ 400 строк (я попытался с odbc, это значение может зависеть от его конфигурации)

Ответ 6

Если у вас есть инструкции insert, которые больше 1000, тогда поместите все инструкции insert в файл .sql и откройте это в Toad или SQL Developer, а затем выполните. Все записи будут вставлены.

Ответ 7

Вы должны рассмотреть Array-Insert.

  • Легкий SQL
  • нужно некоторое кодирование на стороне клиента для настройки параметров массива

Это способ минимизировать сетевой трафик, если в пакете должно быть сделано несколько сотен вставок.