SELECT *
(我只在特殊的废品查询中使用它,通常是在学习对象的模式时使用)。使用它,但如果这样做我会觉得便宜。我的用例是在存储过程中,在该存储过程中,将创建一个本地临时表,该临时表应始终与用于创建该表的基础表匹配。临时表将在稍后填充,因此快速创建temp表而又不会引起冗长的技巧将是
SELECT * INTO #TempTable FROM RealTable WHERE 1 = 0
,特别是对于具有数百个列的表。如果存储过程的使用者是不可知的到动态结果集,那么我将服务出售给
SELECT *
会有任何问题吗?#1 楼
我通常在生产代码中讨厌SELECT *,而且我一直在使用SELECT *导致大量返工。您的案例确实看起来像是在合理使用。我发现SELECT *是必须的地方-它的邪恶堂兄“ INSERT INTO tbl”没有列列表-正在归档中。行被移动到必须具有相同结构的另一个表的情况。
INSERT INTO SalesOrderArchive -- Note no column list
SELECT *
FROM SalesOrder
WHERE OrderDate < @OneYearAgo
DELETE FROM SalesOrder
WHERE OrderDate < @OneYearAgo
如果将来在SalesOrder中添加了新列,但未在SalesOrderArchive中添加,则INSERT将失败。听起来不错,但这实际上是一件好事!因为替代方案要差得多。如果所有列都列在INSERT和SELECT上,则INSERT将成功,随后的DELETE也将成功(实际上是“ DELETE *”)。成功的生产代码不会受到任何关注,并且可能需要很长的时间才能有人注意到新列没有被存档,而是被完全删除。
#2 楼
在生产中,select *有什么用??
或
create table #foo(a int, b int, c int, d int)
...
select * from #foo
,即,当
*
绑定到在同一批次中声明的显式列列表时,仅用于避免多次重复列列表。 当
*
引用表或视图时,例如,在这里,有关缓存的元数据会有一些令人讨厌的复杂性。它并不能真正节省您的输入,因为SSMS允许您拖放完整的列列表。#3 楼
当由SELECT *
引入EXISTS
时,就会有效使用它。如果代码在内部,则添加例如相关的问答:EXISTS(SELECT 1 ...)vs EXISTS(SELECT * ...)一个或另一个?
另请参见:<不好的习惯:使用SELECT * /忽略Aaron Bertrand的列列表。
选择时* Erik Darling没关系。
#4 楼
我将大胆地说出来:生产代码中有SELECT *的用例。任何时候只要您说“我希望对表的任何更改都可以立即反映在对我的结果输出的更改中”,就是这样做的一种情况。让我举几个例子:
用例1-制作一个镜像主表的视图,除了它可以过滤掉敏感的公司专用数据。
在这种情况下,您需要该视图选择 *。输出应该被认为是对主表的反映。输出布局匹配
表布局是功能,而不是错误。
...
用例# 2-制作一个存储的proc,将要更新的一些记录复制到临时保存表中,以防进程
遇到问题(有点麻烦)。
在这种情况下,输出与表本身不匹配的情况很糟糕
-这意味着您可能无法使用
临时保存表中的数据返回到起点。
评论
Re:用例1:在SQL Server中,如果视图执行SELECT * FROM dbo.A(在最高级别),然后将一列添加到dbo.A,则新列将不会自动包含在视图中。您将必须运行sp_refreshview系统SP或发出具有相同视图定义的ALTER VIEW,新列才能出现在输出中。至于用例#2,说实话,我不确定我是否了解这种情况,但是也许我是唯一一个不知道那件事的人,所以不必为可怜的老我详述一下:)
– Andriy M
19年11月23日15:24
我不会将案例2称为“生产代码”。是的,DBA在管理任务中使用“选择*”,最终用户一直在使用它来报告。
– David Browne-微软
19年11月23日15:30
#5 楼
选择*在生产中有什么好的用途?
真的没有。在开发过程中,您提到的方式(选择前n *个)很有意义,但否则会养成不良习惯,并可能导致问题。
您已经谈到了为什么不应该使用它的要点,那就是实际表的结构可能会改变。像上面提到的那样创建一个临时表是一件好事,但是在以后的过程中,可能会导致问题,在您使用一些
INSERT
命令填充临时表之后,返回带有SELECT *
的结果集。现在,您的最终应用程序将检索意外的列。 您也可以使用
SELECT ... INTO #TEMP FROM ...
快速创建临时表。很难知道哪种方法最适合您的情况。SELECT *
的其他大多数问题似乎与您的用例无关紧要视图(当表更改时可能会中断)
绑定问题
表扫描(因为您实际上确实想要所有列)
检索不必要的列(因为您似乎再次想要它们)顺序位置
#6 楼
我对您的问题的回答是“最多/很多用例”您的用例着重说明*为何不可怕。
您的架构将会改变。
由于需要添加字段,为什么要设置自己以接触每个SP?
如果要添加字段,为什么我的UI会在乎?
如果要删除字段,则使用*或CSV都无关紧要,这意味着要进行重大更改。
”如果我的存储过程的使用者与动态结果无关集,...“
这就是使用select *的真正问题。如果您的消费者写得不好,那么您可能会遇到问题。
例如,如果您将Fields [13]格式化为日期...
在某些情况下,我会回避选择*:
缓解延迟-我的使用者很远,他们只需要表中相对较小的字段子集
联接-涉及多个表的复杂查询。消费者可能不需要所有表中的所有字段。实际上,有重复的键列可能应该省略。
我知道我的使用者编写的代码很差-如果您正在开发公共API,我想您有可能希望兑现OpenClose并使其每当字段集更改时,都会使用一个新的api方法。对我来说,这似乎是解决上述问题的一种不好的方法。
总是有象牙塔套装。开放的心态聆听他们的想法。
然后下定决心。
#7 楼
如果添加新列后,始终可以安全地忽略它(例如:从id = @ x的客户中选择名字,姓氏),则永远不会使用select *-您触摸的列越多,发现/创建有用索引的机会就越少。
如果添加新列时,将其静默丢弃将是不好的(任何类型的数据复制),然后使用未指定的select(插入到archiveTable select * from the Table where isOld = true)中的代码这里的失败不是错误,它是一个功能-尤其是在您同时控制数据库和读取表的代码的情况下。
这里的失败机制是不好的-您不会如果您要向此人添加新的喜欢的颜色,则希望您的名字查找失败。
如果您在编写存档代码后添加了该列,则您不想忽略对该人的喜欢的颜色进行存档。
关于连接的说明-sql server将跳过读取以后不使用的任何列
select firtname,email from (select * from profile where isArchived=false)p join (select * from emailaddresses where mostRecentSend < ago(6days))e on p.id=e.profileId
除了名字,id和电子邮件列。
评论
我认为这都不是一个好用例,在这里使用SELECT *是懒惰的。如果查询或表发生更改,您仍然可能会遇到问题。我希望显式更改SELECT,即您的API。
–way0utwest
20年1月1日,下午2:26