SQL Prompt教程:何时使用SELECT…INTO语句(PE003)

SELECT…INTO是开发工作特别是创建临时表的有用捷径。但是,它不再具有明显的性能优势,应在生产代码中避免使用。最好使用CREATE TABLE语句,在该语句中您可以预先指定约束和数据类型,这样就可以减少不一致情况潜入数据的可能性。

SQL Prompt是一款实用的SQL语法提示工具。SQL Prompt根据数据库的对象名称、语法和代码片段自动进行检索,为用户提供合适的代码选择。自动脚本设置使代码简单易读–当开发者不大熟悉脚本时尤其有用。SQL Prompt安装即可使用,能大幅提高编码效率。此外,用户还可根据需要进行自定义,使之以预想的方式工作。

SQL Prompt正式版

我们可以SELECT…INTO在SQL Server中使用表源创建新表。SQL Server使用SELECT列表中表达式的属性来定义新表的结构。

在SQL Server 2005之前,SELECT…INTO在生产代码中使用性能是一种“代码味道”,因为它获取了数据库系统表上的架构锁,从而导致SQL Server在执行查询时显得无响应。这是因为它是隐式事务中的DDL语句,由于将数据插入同一SQL语句中,因此不可避免地要长时间运行。但是,当锁定模型更改时,此行为已在SQL Server 2005中修复。

SELECT…INTO之所以变得流行是因为它是一种比使用插入数据更快的方式INSERT INTO…SELECT…。这主要是由于SELECT…INTO在可能的情况下对该操作进行了大容量日志记录。尽管INSERT INTO现在可以批量登录,但您仍可以在SQL Server 2012和2014中看到这种性能优势,因为SELECT…INTO可以在这些版本上进行并行化,而对并行化的支持INSERT INTO仅在SQL Server 2016中出现。但是,使用SELECT…INTO,您仍然具有在新表上定义所有必需的索引和约束等任务。

SELECT…INTOSQL Prompt(PE003)中的代码分析规则中包含了避免对生产代码使用的建议。

使用SELECT INTO语句创建表

SELECT…INTOSQL Server中的功能旨在将表源存储或“持久化”作为流程的一部分。这是一个简单的示例:

SQL Prompt教程:何时使用SELECT…INTO语句(PE003)

但是,表源可以是常规表以外的很多东西,例如用户定义的函数,an OpenQuery,an OpenDataSource,OPENXML子句,派生表,联接表,数据透视表,远程数据源,表变量或可变函数。正是这些更奇特的表源使SELECT…INTO语法变得更加有用。

SELECT INTO是否是ANSI标准的一部分/strong>

ANSI标准确实支持SELECT…INTO构造。它称为单例选择(singleton select),它会在单行中加载值,但很少使用(感谢Joe Celko指出了这一点)。

人们常常SELECT…INTO误以为这是复制表的一种快速方法,因此令人惊讶的是,没有将源表中定义的索引,约束,计算列或触发器都转移到新表中。也不能在SELECT…INTO语句中指定它们。它还对可空性或保留计算列没有任何作用。必须使用适当的数据来回顾性地完成所有这些任务,这不可避免地要花费时间。

但是,您可以使用函数IDENTITY(数据类型,种子,增量)来设置标识字段,并且当源是单个表时,可以将目标表的列设置为标识列。正是这一事实可能导致开发人员假设它将转移其他列属性。

此外,它也不能创建分区表,稀疏列或从源表继承的任何其他属性。当数据可能来自涉及许多联接的查询或来自某些外部数据源的数据时,该怎么办/span>

自SQL 2012 SP1 CU10起,SELECT…INTO可以并行执行,但是,自SQL Server 2016起,在常规语句中允许并行插入INSERT INTO…SELECT,但有一定的限制,因此使用SELECT…的任何性能优势INTO现在都大大减少了。INSERT INTO如果可以批量记录而不是完全恢复,则可以加快该过程,方法是将恢复模型设置为简单记录或批量记录,插入空表或堆中,并TABLOCK为表设置提示。

以下总结了使用时的一些限制和限制SELECT…INTO。

  • IDENTITY列的属性已转移,但在以下情况下不会转移:

该SELECT语句包含联接的表(使用JOIN或UNION),GROUP BY子句或聚合函数。如果您需要避免将一个IDENTITY属性转移到新表中,但需要该列的值,则值得JOIN在永远不成立的条件下将a添加到表源中,或者UNION不提供任何行。

该IDENTITY列在SELECT列表中被多次列出

该IDENTITY列是表达式的一部分

该IDENTITY列来自远程数据源

  • 你不能SELECT…INTO既表值参数或目的地的表变量,但你可以选择FROM它们。
  • 即使您的源是分区表,也将在默认文件组中创建新表。但是,在SQL Server 2017中,可以通过ON子句指定在其中创建目标表的文件组。
  • 您可以指定一个ORDER BY子句,但通常将其忽略。因此,IDENTITY_INSERT不能保证的顺序。
  • 当SELECT列表中包括计算列时,新表中的对应列不是计算列。新列中的值是在SELECT…INTO执行时计算的值。
  • 与CREATE TABLE语句一样,如果SELECT…INTO语句包含在显式事务中,则受影响的系统表中的基础行将被独占锁定,直到显式提交事务为止。同时,这将导致使用这些系统表的其他进程上的块。

关于SELECT…INTO使用临时表可能发生的问题,有些困惑。SELECT…INTO已经为此获得了不公平的声誉,但这是一个更普遍的问题的一部分,该问题涉及在tempdb小型临时表创建和删除的繁重负载下的闩锁争用。当SELECT…INTO热情地接受时,它可以大大增加这种活动。通过引入跟踪标记TF1118,可以轻松地在SQL Server 2000及更高版本中解决此问题,而从SQL Server 2016开始不再需要此标记。有关完整的解释,请参阅关于TF 1118的误解。

概要

总而言之,SELECT…INTO如果您不关心约束,索引或特殊列,则是使表源作为过程的一部分临时持久化的好方法。这不是复制表的好方法,因为只能复制表架构的最重要的要素。多年来,有一些因素增加或减少了的吸引力SELECT…INTO,但总的来说,最好避免使用它。而是显式地创建一个表,该表具有表所具有的全部功能,这些功能旨在确保数据一致。

试用下载>>>

SQL Prompt 使用教程>>>


想要购买SQL Prompt正版授权,或了解更多产品信息请点击【咨询在线客服】
标签:

来源:慧都

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2020年11月19日
下一篇 2020年11月19日

相关推荐

发表回复

登录后才能评论