为什么使用'*'构建视图不好?
假设您有一个复杂的连接,并且可以在某处使用所有字段.
然后你只需要选择所需的字段.
SELECT field1, field2 FROM aview WHERE ...
视图"aview"可能是 SELECT table1.*, table2.* ... FROM table1 INNER JOIN table2 ...
如果table1和table2中的2个字段具有相同的名称,则会出现问题.
这只是为什么在视图中使用'*'不好的原因?
使用'*',您可以在不同的上下文中使用该视图,因为信息就在那里.
我错过了什么?
问候
我不认为软件中有太多"只是坏",但有很多东西被滥用的方式很糟糕:-)
你给出的例子是*为什么*可能不会给你你期望的东西,我认为还有其他的原因.例如,如果基础表发生更改,可能会添加或删除列,则使用*的视图将继续有效,但可能会破坏使用它的任何应用程序.如果您的视图已明确命名列,那么在进行架构更改时,有人会发现问题的可能性更大.
另一方面,您实际上可能希望您的视图轻松接受对基础表的所有更改,在这种情况下,*就是您想要的.
更新:我不知道OP是否有一个特定的数据库供应商,但现在很清楚,我的上一句话并不适用于所有类型.我非常感谢user12861和Jonny Leeds指出这一点,对不起,我花了6年时间来编辑我的答案.
虽然这里的许多注释非常好,并且引用了在查询中使用通配符的一个常见问题,例如,如果基础表发生更改会导致错误或不同结果,另一个未涵盖的问题是优化.拉取表的每一列的查询往往不如仅提取实际需要的列的查询效率高.当然,有些时候你需要每一列而且它是一个主要的PIA必须全部引用它们,特别是在一个大表中,但是如果你只需要一个子集,为什么要用比你需要的更多的列来阻止你的查询.
" *
"不仅在视图中而且在查询中存在风险的另一个原因是列可以更改名称或更改基础表中的位置.使用通配符意味着您的视图可以轻松容纳此类更改,而无需进行更改.但是,如果应用程序在结果集中按位置引用列,或者如果使用返回按列名称键入的结果集的动态语言,则可能会遇到难以调试的问题.
我总是避免使用通配符.这样,如果列更改名称,我立即在视图或查询中收到错误,并且我知道在哪里修复它.如果列更改基础表中的位置,则指定视图或查询中列的顺序将对此进行补偿.
这些其他答案都有好处,但在SQL服务器上至少它们也有一些错误点.试试这个:
create table temp (i int, j int) go create view vtemp as select * from temp go insert temp select 1, 1 go alter table temp add k int go insert temp select 1, 1, 1 go select * from vtemp
添加时,SQL Server不会了解"新"列.根据你的需要,这可能是件好事还是坏事,但无论哪种方式,依赖它都可能并不好.所以避免它只是一个好主意.
对我来说,这种奇怪的行为是避免在视图中选择*的最有说服力的理由.
这些评论告诉我,MySQL有类似的行为而Oracle没有(它将了解对表的更改).这与我的不一致是更多的理由不在视图中使用select*.
使用'*'进行任何生产都很糟糕.这对于一次性查询非常有用,但在生产代码中,您应始终尽可能明确.
特别是对于视图,如果基础表添加或删除了列,则视图将被错误或中断,直到重新编译为止.