插入到选择


127

使用之间有什么区别

SELECT ... INTO MyTable FROM...

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

从BOL [ INSERTSELECT ... INTO ]中,我知道使用SELECT ... INTO将在默认文件组上创建插入表如果尚不存在),并且该语句的日志记录取决于恢复情况数据库的模型。

  1. 哪种说法更可取?
  2. 还有其他性能影响吗?
  3. 通过INSERT INTO ...进行SELECT ... INTO的好用例是什么?

编辑:我已经说过,我知道SELECT INTO ...会创建一个不存在的表。我想知道的是SQL包含此语句是有原因的,它是什么?它是做幕后的东西不同的插入行,或者是它的顶部只是语法糖CREATE TABLEINSERT INTO


一个小因素:INSERT INTO前面有两个关键词(选择并进入),它们使世界知道这不是普通的SQL语句,而SELECT ... INTO至少在开始时看起来像普通的SQL语句。支持前者的一个小理由。
Martin F

Answers:


122
  1. 他们做不同的事情。INSERT该表存在时使用。不使用SELECT INTO时使用。

  2. 是。 INSERT通常没有记录表提示。 SELECT INTO假设设置了正确的跟踪标志,则最小记录日志。

  3. 以我的经验SELECT INTO,最常用的是中间数据集(如#temp表),或复制整个表(如备份)。 INSERT INTO当您插入具有已知结构的现有表时使用。

编辑

为了解决您的修改,他们做了不同的事情。如果要制作表并想定义结构,请使用CREATE TABLEINSERT。可能出现的问题的示例:您有一个带有varchar字段的小表。现在,表中的最大字符串为12个字节。您的实际数据集最多需要200个字节。如果您SELECT INTO从小型表中创建一个新表,则后者INSERT将因截断错误而失败,因为您的字段太小。


4
我的两分钱,我认为引入失败是一件好事。我想知道我的数据是否与预期的数据格式/大小不匹配。我总是尝试使用CREATE TABLE,然后使用来定义我的表。INSERT INTO此外SELECT,无需执行插入操作即可更轻松地单独测试语句。
道格·张伯伦

1
@道格-我同意。我几乎专门用于SELECT INTO制作临时表或对将要使用的现有表进行快速备份。
JNK

1
@JNK-在BOL中,SELECT INTO根据选择列表中列的数据类型创建具有结构的表。因此,在您的示例中,您可以通过将varchar显式转换为足够的大小来纠正这种情况。正确?
jowenece 2011年

2
@Jowenece-是的,我希望如此。如果要解决这个问题,我将继续并使用一条CREATE语句。
JNK

24
  1. 哪种说法更可取? 取决于您在做什么。

  2. 还有其他性能影响吗?如果该表是永久性表,则可以在创建表时创建索引,这会对性能产生负面影响。Select into不会重新创建当前表上存在的索引,因此表的后续使用可能比所需的速度慢。

  3. 通过INSERT INTO ...进行SELECT ... INTO的好用例是什么?如果您可能事先不知道表结构,则使用select into。它比创建表和插入语句要快,因此有时可以加快开发速度。当您创建快速临时表来测试事物或特定查询的备份表(可能是要删除的记录)时,使用它通常会更快。很少会看到它会在生产代码中运行多次(临时表除外),因为如果表已经存在,它将失败。

有时不知道自己在做什么的人会不恰当地使用它。因此,它们可能导致数据库损坏。我强烈认为将SELECT INTO用于除临时表(临时备份,临时表会在存储proc的末尾消失等)之外的其他操作是不合适的。永久表需要对其设计进行真正的思考,而SELECT INTO可以轻松地避免考虑任何内容,即使是最基本的内容(如列和数据类型)也是如此。

通常,我更喜欢使用create table和insert语句-您拥有更多控件,并且对于可重复的过程而言更好。此外,如果该表是永久性表,则应从单独的创建表脚本(在源代码控制中的一个)中创建该表,因为创建永久性对象通常不应在代码中插入/删除/更新或从一个表中进行选择。表。对象更改应与数据更改分开处理,因为对象的含义超出了特定插入/更新/选择/删除的需要。您需要考虑最佳的数据类型,考虑FK约束,PK和其他约束,考虑审核要求,考虑建立索引等。


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中,因为它使诸如临时报告或复制表之类的任务变得更加容易。


CREATE TABLE和SELECT INTO是完全相同的事情(不需要INSERT INTO作为完成SELECT INTO的工作的补充),我不建议选择SELECT INTO。参见dba.stackexchange.com/questions/156105/…
里克'18

4

每个语句都有不同的用例。它们不可互换。

SELECT...INTO MyTable...创建MyTable一个以前不存在的新对象。

INSERT INTO MyTable...SELECT...MyTable已存在时使用。


4
您没有回答我的任何问题,我已经陈述了您的答案。
jowenece 2011年

5
暗含您问题的答案。更清楚地说,没有“首选”语句,因为每个语句都有不同的用例。语句不可互换。当您要创建一个不存在的新表时,请使用第一个版本。该表已存在时,请使用第二个版本。
Joe Stefanelli

2
与创建临时表然后插入临时表相比,我为什么要这样做?有优势吗?
jowenece 2011年

4

实际上SELECT ... INTO不仅会创建表,而且如果表已经存在也会失败,因此,基本上,只有当插入表不存在时,您才会使用它。

关于您的编辑:

我个人在创建临时表时主要使用SELECT ... INTO。这对我来说是主要用途。但是,在创建具有许多与其他表具有相似结构的列的新表并进行编辑以节省时间时,我也会使用它。


1
我主要也看到了SELECT..INTO在临时表中的使用,但是有没有理由更喜欢使用CREATE TABLE语句创建临时表呢?例如-性能提升?
jowenece 2011年

3
@jowenece我想主要是为了简化...也说您有一个动态查询。我不知道结构,无法事先创建表,使用SELECT ... INTO比动态创建表要容易得多。
AJC

3

SELECT INTO通常用于生成临时表或复制另一个表(数据和/或结构)。

在日常代码中,您将使用INSERT,因为您的表应该已经存在,可以读取,更新,删除,联接等。注意:INSERT关键字对于INSERT是可选的

也就是说,应用程序通常不会作为正常操作的一部分来创建和删除表,除非它是用于某些范围限制和特定用途的临时表。

SELECT INTO创建的表将没有键,索引或约束,这与真实的,持久的,已经存在的表不同

这两个不能直接比较,因为它们的用法几乎没有重叠


2

我只想介绍与绩效有关的第二点,因为没有其他人对此进行了介绍。对于具有大型数据集的表,“选择插入”比“插入插入”要快得多。当我不得不阅读一个非常大的表时,我更喜欢选择。对于具有一千万行的表,insert into可能要花费数小时,而select into将在数分钟内完成,至于丢失新表上的索引,您可以通过查询来重新创建索引,并且与之相比仍可以节省更多时间插入。


是的,但这主要是因为SQL Server知道目标表没有争用。的演出insert into #temp with(tablock) select * from ..select * into #temp from ...
Brian

1

Select into当时为您创建一个新表,然后从源表中插入记录。新创建的表与源表具有相同的结构。如果尝试对现有表使用select into,则会产生错误,因为它将尝试创建具有相同名称的新表。在表中插入行之前,需要在数据库中存在该表。


1

select Into和Insert Into之间的简单区别是:-> Select Into不需要现有表。如果要复制表A的数据,只需从A键入Select * INTO [表名]。在这里,表名可以是现有表,也可以创建具有与表A相同结构的新表。

->插入到确实需要现有的表。插入到[表名] SELECT * FROM A;。这里的tablename是一个现有的表。

Select Into通常更流行用于复制数据,尤其是备份数据。

您可以根据需要使用,这完全是开发人员的选择,应该在他的方案中使用。

明智的插入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。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.