【问题标题】:'SELECT *' from inner joined tables'SELECT *' 来自内部连接表
【发布时间】:2009-05-18 14:07:23
【问题描述】:

如何选择两个连接表的所有字段,而不与公共字段冲突?

假设我有两个表,ProductsServices。我想这样查询:

SELECT Products.*, Services.* 
FROM Products 
INNER JOIN Services ON Products.IdService = Services.IdService

这个查询的问题是IdService会出现两次,导致一堆问题。

到目前为止,我发现的替代方法是从 Products 中区分每个字段,IdService 除外。但这样我每次向Products 添加新字段时都必须更新查询。

有没有更好的方法来做到这一点?

【问题讨论】:

  • 你可以使用自然连接吗?它会自动执行您想要的操作。
  • 我使用的是 SQL Server 2005,我不认为 N​​ATURAL JOIN 和 COMPOSE 可以在这里工作。
  • 好的,鉴于“你不应该那样做”的答案的数量,我承认我一定是走错了方向。我不会再使用 SELECT * 了。

标签: sql sql-server inner-join


【解决方案1】:

您不应该在生产代码中使用 SELECT *(嗯,几乎从来没有,但是可以很容易地计算出合理的次数)。

【讨论】:

  • 如果我想从此查询创建视图怎么办?
  • 这还是个坏主意。根据您的 RDBMS,在您重新编译之前,视图不会更新它自己的字段列表,因此您一无所获,或者在这种情况下您会遇到与表相同的问题 - 更改基础表可能会突然破坏应用程序。
  • 一种合理的情况(我敢肯定你不能数这些)是存在子句之后的子查询。比如“where id not in (select * from table where linkid = id”)
  • @Adnomar。是的,但你并没有真正做“选择 *”,只是 SQL 没有更好的方法来表达半连接。
  • @MichaelCalkins 如果这个问题是给我的,我没有读过它只是意识到。
【解决方案2】:

What are the most common SQL anti-patterns?

您遇到了反模式 #1。

更好的方法是提供一个字段列表。获得快速字段列表的一种方法是

sp_help tablename

如果您想从此查询创建视图 - 使用 select * 会给您带来更多麻烦。 SQL Server 在创建视图时捕获列列表。如果您编辑基础表并且不重新创建视图 - 您正在注册麻烦(我遇到了这种性质的生产火灾 - 视图是针对不同数据库中的表)。

【讨论】:

    【解决方案3】:

    据我所知,您必须避免使用SELECT *,但这并不是问题。

    SELECT * 通常被认为是一个等待发生的问题,因为您引用的原因是优势!通常,当数据库被修改时,为查询出现的额外结果列会导致问题。

    【讨论】:

      【解决方案4】:

      您的 SQL 方言是否支持 COMPOSE? COMPOSE 删除了在等值连接上使用的列的额外副本,就像您的示例中的那样。

      【讨论】:

        【解决方案5】:

        正如其他人所说,Select * 是个坏消息,特别是如果将其他字段添加到您正在查询的表中。您应该从表中选择所需的确切字段,并且可以为具有相同名称的字段使用别名,或者只使用 table.columnName。

        【讨论】:

          【解决方案6】:

          不要使用 *.使用这样的东西:

          SELECT P.field1 AS 'Field from P'
               , P.field2
               , S.field1 AS 'Field from S'
               , S.field4 
            FROM Products P
                 INNER JOIN 
                 Services S
                 ON P.IdService = S.IdService
          

          【讨论】:

            【解决方案7】:

            没错,列出你想要的字段(在 SQL Server 中,你可以将它们从对象浏览器中拖过来,这样你就不必全部输入)。顺便说一句,如果您的特定查询不需要某些字段,请不要列出它们。这会为服务器带来额外的工作并占用额外的网络资源,并且可能是在整个系统中执行此操作时性能不佳的原因之一,并且此类浪费的查询每天会运行数千次。

            至于这是一个维护问题,您只需要添加这些字段,如果使用您的查询的应用程序部分会受到它们的影响。如果您不知道新字段会产生什么影响或需要在何处添加它,则不应添加该字段。此外,通过使用 select * 意外添加新文件也会导致维护问题。制造性能问题以避免进行维护(您甚至可能永远不需要进行维护,因为列更改应该很少见(如果不是,您需要查看您的设计))是非常短视的。

            【讨论】:

              【解决方案8】:

              最好的方法是从查询中指定您想要的确切字段。无论如何你都不应该使用*

              使用* 获取所有字段很方便,但它不会产生健壮的代码。表中的任何更改都会更改查询返回的结果,这并不总是可取的。

              您应该只从查询中返回您真正想要的数据,并按照您想要的确切顺序指定。这样,即使您向表中添加字段或更改表中字段的顺序,结果看起来也完全相同。

              指定确切的输出需要做更多的工作,但从长远来看,它通常会得到回报。当您进行更改时,只有您实际更改的内容会受到影响,您不会得到破坏您甚至不知道受到影响的代码的级联效果。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2016-10-30
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2021-06-24
                • 2016-01-28
                相关资源
                最近更新 更多