插入与选择

使用

SELECT ... INTO MyTable FROM...

还有

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

从 BOL [ 插入选择... 进入] ,我知道使用 SELECT... INTO 将创建插入表 在默认文件组上(如果它不存在的话) ,并且该语句的日志记录取决于数据库的恢复模式。

  1. 哪种说法更好?
  2. 还有其他性能影响吗?
  3. 什么是 SELECT... INTO 而不是 INSERT INTO... 的好用例?

编辑: 我已经说过,我知道 SELECTINTO... 创建了一个不存在的表。我想知道的是,SQL 包含这个语句是有原因的,它是什么?它是在后台为插入行做了一些不同的事情,还是仅仅在 CREATE TABLEINSERT INTO之上添加了语法糖。

142051 次浏览

每个语句都有一个独特的用例,它们是不可互换的。

SELECT...INTO MyTable...创建了一个以前不存在的新 MyTable

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

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

在日常代码中,您使用 INSERT,因为您的表应该已经存在以供读取、 UPDATEd、 DELETED、 JOINED 等。注意: INTO 关键字在 INSERT 中是可选的

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

SELECTINTO 创建的表与实际的、持久化的、已经存在的表不同,没有键、索引或约束

两者之间没有直接的可比性,因为它们的用法几乎没有重叠

主要区别在于,SELECT INTO MyTable 将创建一个名为 MyTable 的新表并显示结果,而 INSERT INTO 则要求 MyTable 已经存在。

只有在表不存在并且希望基于查询结果创建表的情况下,才会使用 SELECTINTO。因此,这两种说法实在是没有可比性。他们做的事情完全不同。

一般来说,SELECTINTO 更多地用于一次性任务,而 INSERTINTO 通常用于向表中添加行。

编辑:
虽然您可以使用 CREATETABLE 和 INSERTINTO 来完成 SELECTINTO 的工作,但是使用 SELECTINTO 时,您不必事先知道表的定义。SELECTINTO 可能包含在 SQL 中,因为它使临时报告或复制表之类的任务更加容易。

  1. 它们做不同的事情。当表存在时使用 INSERT。当表不存在时使用 SELECT INTO

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

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

剪辑

为了解决你的编辑,他们做不同的事情。如果您正在制作一个表,并且希望定义这个结构,那么可以使用 CREATE TABLEINSERT。可以创建的问题示例: 您有一个带有 varchar 字段的小表。现在表中最大的字符串是12字节。您的真实数据集将需要多达200个字节。如果你在你的小桌子上做一个新的 SELECT INTO,后面的 INSERT会因为你的截尾误差太小而失败。

实际上,选择... 进入不仅创建了表,而且如果表已经存在,它也会失败,所以基本上只有在插入到的表不存在的时候才会使用它。

关于你的编辑:

我个人在创建临时表时主要使用 选择... 进入。这对我来说是主要用途。但是,我也使用它来创建具有许多与其他表类似结构的列的新表,然后编辑它,以节省时间。

  1. 哪种陈述更好? 取决于你在做什么。

  2. 还有其他性能影响吗? 如果表是一个永久表,您可以在创建表时创建索引,这对性能有负面和正面的影响。选择并不会重新创建当前表上存在的索引,因此后续使用该表的速度可能会慢于需要的速度。

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

它有时被不知道自己在做什么的人不恰当地使用。结果,它们会对数据库造成严重破坏。我强烈认为,除了一个一次性表(一个临时备份,一个将在存储过程结束时消失的临时表,等等)之外,对其他任何东西使用 SELECT INTO 都是不合适的。永久表的设计需要 真正的想法,而 SELECT INTO 使得人们很容易避免考虑任何东西,即使是像什么列和什么数据类型这样基本的东西。

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

选择“当时为您创建新表”,然后从源表向其中插入记录。新创建的表具有与源表相同的结构。如果您尝试对现有表使用 select into,它将产生一个错误,因为它将尝试创建具有相同名称的新表。 在向数据库中插入行之前,“插入”要求表必须存在于数据库中。

我只想讨论与性能有关的问题的第二点,因为没有其他人讨论过这个问题。当涉及到具有大型数据集的表时,选择 Into 要比插入快得多。当我必须读取一个非常大的表时,我更喜欢选择。对于一个有1000万行的表,插入操作可能需要几个小时,而 select into 将在几分钟内完成。至于新表中丢失索引的问题,可以通过查询重新创建索引,与插入操作相比,仍然可以节省更多的时间。

对于大型数据集,只有对于单个用户使用到数据库的单个连接执行批量操作任务时,才可以选择。我不建议使用

SELECT * INTO table

因为这将创建一个大事务并创建模式锁来创建对象,从而阻止其他用户创建对象或访问系统对象,直到 SELECT INTO操作完成。

作为概念的证明打开2会话,在第一会话中尝试使用

select into temp table from a huge table

在第二部分尝试

create a temp table

并检查锁、阻塞和第二个会话的持续时间,以创建一个临时表对象。我的建议是,创建和插入语句始终是一个很好的实践,如果需要最小化日志记录,可以使用跟踪标志610。

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

插入确实需要现有的 table. INSERT INTO [ tablename ] SELECT * FROM A; 。 这里的表名是一个现有的表。

选择“进入”通常更常用于复制数据,特别是备份数据。

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

性能方面,InsertINTO 速度很快。

参考文献:

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

其他的答案都很好/正确(主要区别在于 DestTable是否已经存在(INSERT) ,或者还不存在(SELECT ... INTO))

您可能更喜欢使用 INSERT(而不是 SELECT ... INTO) ,如果你想能够 COUNT(*)的行已经插入到目前为止。

使用 SELECT COUNT(*) ... WITH NOLOCK是一种简单/粗糙的技术,它可以帮助您检查 INSERT的“进度”; 如果它是一个长时间运行的插入(从这个答案中可以看出) ,那么这种技术将很有帮助。

[如果你使用... ] INSERT DestTable SELECT ... FROM SrcTable 那你的 SELECT COUNT(*) from DestTable WITH (NOLOCK)查询就可以了。