INSERT INTO против SELECT INTO

127

В чем разница между использованием

SELECT ... INTO MyTable FROM...

и

INSERT INTO MyTable (...)
SELECT ... FROM ....

?

Из BOL [ INSERT , SELECT ... INTO ] я знаю, что использование SELECT ... INTO создаст таблицу вставки в группе файлов по умолчанию, если она еще не существует, и что ведение журнала для этого оператора зависит от восстановления модель базы данных.

  1. Какое утверждение предпочтительнее?
  2. Есть ли другие последствия для производительности?
  3. Как лучше использовать SELECT ... INTO вместо INSERT INTO ...?

Изменить: я уже заявил, что знаю, что SELECT INTO ... создает таблицу, в которой ее не существует. Я хочу знать, что SQL включает этот оператор по какой-то причине, что это такое? Делает ли он что-то другое за кулисами для вставки строк, или это просто синтаксический сахар поверх CREATE TABLEи INSERT INTO.

jowenece
источник
Один небольшой фактор: сразу INSERT INTOдва ключевых слова (select & into), которые дают миру понять, что это не обычный оператор SQL, хотя SELECT ... INTOначинает, по крайней мере, выглядеть как обычный оператор SQL. Небольшая причина отдать предпочтение первому.
Martin F

Ответы:

122
  1. Они делают разные вещи. Используйте, INSERTкогда таблица существует. Используйте, SELECT INTOкогда это не так.

  2. Да. INSERTбез табличных подсказок обычно регистрируется. SELECT INTOминимально регистрируется при условии, что установлены правильные флаги трассировки.

  3. По моему опыту SELECT INTO, чаще всего используется с промежуточными наборами данных, такими как #tempтаблицы, или для копирования всей таблицы, например, для резервного копирования. INSERT INTOиспользуется при вставке в существующую таблицу с известной структурой.

РЕДАКТИРОВАТЬ

Чтобы решить вашу проблему редактирования, они делают разные вещи. Если вы составляете таблицу и хотите определить структуру, используйте CREATE TABLEи INSERT. Пример проблемы, которая может быть создана: у вас есть небольшая таблица с полем varchar. Самая большая строка в вашей таблице теперь составляет 12 байтов. Вашему реальному набору данных потребуется до 200 байт. Если вы сделаете SELECT INTOиз своей небольшой таблицы новую, последняя INSERTзавершится ошибкой с ошибкой усечения, потому что ваши поля слишком малы.

JNK
источник
4
Мои два цента, я считаю, что провал - это хорошо. Я хочу знать, соответствуют ли мои данные ожидаемому формату / размеру данных. Я всегда пытаюсь определить свою таблицу с помощью, CREATE TABLEа затем. INSERT INTOКроме того, проще протестировать SELECTинструкцию самостоятельно, не выполняя вставку.
Дуг Чемберлен
1
@Doug - согласен. Я почти исключительно использую, SELECT INTOчтобы сделать временную таблицу или сделать быстрое резервное копирование существующей таблицы, с которой я собираюсь обезопасить себя.
JNK
1
@JNK - из BOL, SELECT INTO создает таблицу со структурой на основе типов данных столбцов в списке выбора. Итак, в вашем примере вы можете исправить ситуацию, явно приведя varchar к размеру, который будет достаточным. Верный?
jowenece
2
@Jowenece - да, я так и ожидал. Если я собираюсь столкнуться с этой проблемой, я собираюсь пойти дальше и использовать CREATEзаявление.
JNK,
24
  1. Какое утверждение предпочтительнее? Зависит от того, что вы делаете.

  2. Есть ли другие последствия для производительности? Если это постоянная таблица, вы можете создавать индексы во время создания таблицы, что отрицательно и положительно сказывается на производительности. Select into не воссоздает индексы, существующие в текущих таблицах, и поэтому последующее использование таблицы может быть медленнее, чем должно быть.

  3. Как лучше использовать SELECT ... INTO вместо INSERT INTO ...? Select into используется, если вы не знаете структуру таблицы заранее. Это быстрее написать, чем создать таблицу и оператор вставки, поэтому он используется для ускорения разработки в разы. Часто бывает быстрее использовать, когда вы создаете быструю временную таблицу для тестирования или резервную копию определенного запроса (возможно, записи, которые вы собираетесь удалить). Редко можно увидеть его использование в производственном коде, который будет выполняться несколько раз (за исключением временных таблиц), потому что он завершится ошибкой, если таблица уже существует.

Иногда его ненадлежащим образом используют люди, которые не знают, что делают. И в результате они могут вызвать хаос в базе данных. Я категорически считаю неуместным использовать SELECT INTO для чего-либо, кроме одноразовой таблицы (временная резервная копия, временная таблица, которая исчезнет в конце сохраненной процедуры и т. Д.). Постоянные таблицы должны реальные мысли , чтобы их дизайн и SELECT INTO позволяет легко не думать ни о чем даже основные, какие столбцы и какие типы данных.

В общем, я предпочитаю использовать команду create table и insert - у вас больше элементов управления, и это лучше для повторяемых процессов. Кроме того, если таблица является постоянной таблицей, она должна быть создана из отдельного сценария создания таблицы (тот, который находится в системе управления версиями), поскольку создание постоянных объектов, как правило, не должно в коде вставлять / удалять / обновлять или выбирать из стол. Изменения объекта должны обрабатываться отдельно от изменений данных, поскольку объекты имеют последствия, выходящие за рамки потребностей конкретной вставки / обновления / выбора / удаления. Вам необходимо рассмотреть лучшие типы данных, подумать об ограничениях FK, PK и других ограничениях, рассмотреть требования аудита, подумать об индексировании и т. Д.

HLGEM
источник
5

Основное отличие состоит в том, что SELECT INTO MyTable создаст новую таблицу с именем MyTable с результатами, а INSERT INTO требует, чтобы MyTable уже существовал.

Вы должны использовать SELECT INTO только в том случае, если таблица не существует и вы хотите создать ее на основе результатов вашего запроса. По сути, эти два утверждения несопоставимы. Они делают разные вещи.

Как правило, SELECT INTO чаще используется для одноразовых задач, а INSERT INTO используется регулярно для добавления строк в таблицы.

РЕДАКТИРОВАТЬ:
хотя вы можете использовать CREATE TABLE и INSERT INTO для выполнения того, что делает SELECT INTO, с SELECT INTO вам не нужно заранее знать определение таблицы. SELECT INTO, вероятно, включен в SQL, поскольку он значительно упрощает такие задачи, как создание специальных отчетов или копирование таблиц.

rsbarro
источник
CREATE TABLE и SELECT INTO - это почти одно и то же (INSERT INTO не нужен как дополнение для выполнения того, что делает SELECT INTO), а SELECT INTO, я думаю, не рекомендуется. См. Dba.stackexchange.com/questions/156105/… .
Рик
4

У каждого оператора есть отдельный вариант использования. Они не взаимозаменяемы.

SELECT...INTO MyTable...создает новый MyTableтам, где его раньше не было.

INSERT INTO MyTable...SELECT...используется, если MyTableуже существует.

Джо Стефанелли
источник
4
Вы не ответили ни на один из моих вопросов, и я уже изложил ваш ответ.
jowenece
5
Подразумеваются ответы на ваши вопросы. Чтобы было понятнее, не существует «предпочтительного» утверждения, поскольку у каждого есть отдельный вариант использования. Заявления не взаимозаменяемы. Используйте первую версию, если хотите создать новую таблицу, которой не существует. Используйте вторую версию, если таблица уже существует.
Джо Стефанелли
2
Зачем мне это делать, а не создавать временную таблицу, а затем вставлять в нее? Есть ли преимущество?
jowenece
4

На самом деле SELECT ... INTO не только создает таблицу, но и завершается ошибкой, если она уже существует, поэтому в основном вы могли бы использовать ее только тогда, когда таблица, в которую вы вставляете, не существует.

Что касается вашего EDIT:

Лично я в основном использую SELECT ... INTO, когда создаю временную таблицу. Для меня это главное использование. Однако я также использую его при создании новых таблиц с множеством столбцов со структурой, аналогичной другим таблицам, а затем редактирую их, чтобы сэкономить время.

АЕК
источник
1
В основном я вижу использование SELECT..INTO и для временных таблиц, но есть ли причина предпочесть это созданию временной таблицы с помощью оператора CREATE TABLE? Например - прирост производительности?
jowenece
3
@jowenece Я думаю, в основном для простоты ... Также скажем, что у вас есть динамический запрос. Если вы не знаете структуру, вы не можете создать таблицу заранее, и ее намного проще использовать SELECT ... INTO, чем создавать таблицу динамически.
AJC
3

SELECT INTO обычно используется для создания временных таблиц или для копирования другой таблицы (данных и / или структуры).

В повседневном коде вы используете INSERT, потому что ваши таблицы уже должны существовать для чтения, UPDATEd, DELETEd, JOINed и т. Д. Примечание: ключевое слово INTO является необязательным для INSERT

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

Таблица, созданная с помощью SELECT INTO, не будет иметь ключей, индексов или ограничений в отличие от реальной, постоянной, уже существующей таблицы.

Эти 2 нельзя напрямую сравнивать, потому что они почти не совпадают в использовании.

ГБН
источник
2

Я хочу затронуть только второй пункт вопроса, связанный с производительностью, потому что никто другой не рассматривал этот вопрос. Select Into намного быстрее, чем вставка в, когда дело касается таблиц с большими наборами данных. Я предпочитаю выбирать, когда мне нужно прочитать очень большую таблицу. Вставка в таблицу с 10 миллионами строк может занять несколько часов, в то время как select into сделает это за минуты, а что касается потери индексов в новой таблице, вы можете воссоздать индексы по запросу и при этом сэкономить намного больше времени по сравнению с вставить в.

Niraj
источник
Это правда, но в основном потому, что SQL Server знает об отсутствии конкуренции за целевую таблицу. Производительность для insert into #temp with(tablock) select * from ..примерно такая же, как дляselect * into #temp from ...
Брайан
1

Select into создает для вас новую таблицу, а затем вставляет в нее записи из исходной таблицы. Вновь созданная таблица имеет ту же структуру, что и исходная таблица. Если вы попытаетесь использовать select into для существующей таблицы, она выдаст ошибку, потому что она попытается создать новую таблицу с тем же именем. Вставка в требует, чтобы таблица существовала в вашей базе данных, прежде чем вы вставляете в нее строки.

Сатиш Вишвакарма
источник
1

Простая разница между select Into и Insert Into: -> Select Into не требует существующей таблицы. Если вы хотите скопировать данные таблицы A, вы просто набираете Select * INTO [tablename] из A. Здесь имя таблицы может быть существующей таблицей, или будет создана новая таблица, имеющая такую ​​же структуру, как таблица A.

-> Вставить в существующую таблицу. ВСТАВИТЬ В [имя таблицы] ВЫБРАТЬ * ИЗ A ;. Здесь tablename - существующая таблица.

Select Into обычно более популярен для копирования данных, особенно данных резервного копирования.

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

Мудрая производительность Insert INTO работает быстро.

Ссылки :

https://www.w3schools.com/sql/sql_insert_into_select.asp https://www.w3schools.com/sql/sql_select_into.asp

Адитья Пармар
источник
-2

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

SELECT * INTO table

поскольку это создает одну большую транзакцию и блокировку схемы для создания объекта, не позволяя другим пользователям создавать объект или получать доступ к системным объектам до завершения SELECT INTOоперации.

В качестве доказательства концепции откройте 2 сеанса, в первом сеансе попробуйте использовать

select into temp table from a huge table 

а во втором разделе попробуйте

create a temp table 

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

user6802184
источник