【.com快译】如今,网上很多文章都明确指出,使用“SELECT*”作为SQL查询方式是一种极其危险的代码编写习惯。开发者在自己的程序中应该尽量避免这样的查询,而是显式指定要查询的列名。然而,大家可能只是“知其然,不知其所以然”。在本文中,让我向各位初级开发人员详细解释,这种SQL查询最佳实践背后的具体原因。首先,我们经常面临的客观情况是:在Oracle数据库中,很多SQL开发人员都是通过接触“SELECT*fromEMP”(EMP是表名)等查询语句开始学习SQL语言的。因此,除非能给出充分的理由,否则很难改掉他们使用这种方便查询的习惯。下面,我将根据自己在应用程序编程中的实际经验,向大家证明使用Select*fromtable进行SQL查询的“七大罪过”。1.不必要的I/O(输入/输出)使用SELECT*,虽然可以获得一些可以完全忽略的返回数据,但是获取过程并不是免费的。以前可能只需要从索引页读取的数据检索,现在您必须从每个页面完整读取它。显然,这会导致数据库端各种有限的I/O周期的浪费。此外,此方法可能会减慢您的查询速度。如果你很好奇,想探究数据库背后的查询执行过程,以及查询引擎是如何按顺序处理查询语句的,建议你参考:《SQL Performance Explained》byMarkusWinand(见http://www.amazon.com/Performance-Explained-Everything-Developers-about/dp/3950307826/?tag=javamysqlanta-20),以及Udemy的《The Complete SQL BootCamp》(参见https://click.linksynergy.com/fs-bin/click?id=JVFxdTr9V80&subid=0&offerid=323058.1&type=10&tmpid=14538&RD_PARM1=https%3A%2F%2Fwww.udemy.com%2Fthe-complete-sql-bootcamp%2F)课程。2、网络流量增加虽然SELECT*可以返回比用户预期更多的数据,但相应地,这些数据的传输必然会消耗更多的网络带宽资源。同时,网络带宽的增加意味着用户真正需要的数据将需要更长的时间才能传输到客户端应用程序。例如:如果您可能在本地计算机上运行SQLServerManagementStudio(有关详细信息,请参阅http://bit.ly/2CXPyBB)、Toad或SQLDeveloperforOracle(请参阅http://bit.ly/2xQzAsd)提供查询编辑器,或在Java应用服务器上运行此类查询,将消耗大量网络流量和资源。3.更多的应用程序内存随着业务数据的快速增加,你的应用程序可能需要使用更多的内存来保存这类查询产生的数据,这些数据可能来自MicrosoftSQLServer(见http://www.java67.com/2018/01/top-4-free-microsoft-sql-server-books.html)各种无用数据。4.生成依赖于列排序的结果集(ResultSet)。当你在应用程序中使用SELECT*查询时,你会得到一些依赖于数据表的列排序的结果集。因此,一旦增加了新的列,或者修改了列的排序方式,都会对查询结果集产生不同的影响。5.添加新列会破坏现有视图。如果您在视图中(请参阅http://www.java67.com/2012/11/what-is-difference-between-view-vs-materialized-view-database-sql.html),一旦新列添加并从表中删除旧列,您构建的原始视图将被破坏,并将错误的结果返回给用户。为避免发生此类情况,您应该始终在SQLServer数据库之间进行选择(请参阅http://javarevisited.blogspot.sg/2013/11/difference-between-char-varchar-nchar-nvarchar-sql-database.html#axzz5CSnhvSWV),视图的定义包括WITHSCHEMABINDING选项。6.joinquery中的冲突如果你在joinquery中(JOINQuery,见https://javarevisited.blogspot.com/2012/11/how-to-join-three-tables-in-sql-query-mysql-sqlserver.html#axzz5az3hfsHW)使用SELECT*,所以一旦多个表中出现同名的列,比如status、active和name等,可能会出现各种并发冲突。虽然在直接查询中,出现问题的可能性不大,但是当你尝试按其中一个列进行排序时,或者在公用表表达式(CommonTableExpression,CTE)和派生表(derivedtable)中使用查询时,您需要进行各种进一步的调整以避免冲突。7.在表之间复制数据时的风险您可能经常使用诸如“SELECT*intoINSERT...”之类的语句将一些数据从一个表复制到另一个表。如果两个表中列的顺序略有不同,则可能会将不正确的数据复制到错误的列中。有的程序员可能会认为,因为查询解析器要额外验证一些静态值,所以才会出现EXISTS语句(译者注:即验证查询结果是否返回数据,参见https://javarevisited.blogspot。com/2016/01/sql-exists-example-customers-who-never-ordered.html)使用SELECT*比SELECT1更快。过去这种观点可能有些道理。但是现在,各种数据库解析器已经发展得相当智能了。他们判断EXISTS语句的效率并生成SELECT结果列表(参见https://javarevisited.blogspot.com/2016/04/how-to-convert-result-of-select-command-to-comma-separated-String-in-SQL-Server.html)将与它无关。结语通过以上七点的分析,相信你应该明白为什么不能在SQL查询中滥用SELECT*了吧?可以看出,在查询中应该尽可能使用显式的列名,而不是那些星号通配符。这不仅会提高你的代码效率,也会让你的程序更加清晰。同时,这种方法还可以帮助您创建各种可维护的代码。此外,如果稍后向表中添加新列,您的代码不会受到影响,您仍将拥有原始数据表的引用视图。原标题:7ReasonsWhyUsingSELECT*FROMTABLEinSQLQueryIsaBadIdea,作者:JavinPaul
