【问题标题】:What is the proper syntax in SQL Server for addressing tables?SQL Server 中用于寻址表的正确语法是什么?
【发布时间】:2012-04-05 16:53:31
【问题描述】:

这似乎是一个相当明显的问题,但我一直想不出合适的术语来表达我要问的问题,因此为此提供参考材料一直很棘手。不过,答案似乎很明显。

在检查 SQL Server 的 Pluralsight 培训材料时,他们建议始终在“常规”查询(您可能为基本 Web 服务编写的)和存储过程中的 SQL 查询中引用表,如下所示:

[databasename].[dbo].[some_table].[sometimesacolumngoeshere]

虽然我发现存储过程等很常见,但只需使用:

my_column    or    [my_column]

这里的区别显然是一个明确地提供了一个绝对的“地址”,而另一个是隐式的。

你怎么知道什么时候适合使用一个而不是另一个,以及你怎么称呼它?

我的偏好是始终明确,如果您需要节省空间和/或使事情更清楚,您可以别名为明确的完整“地址”,对吗?

【问题讨论】:

    标签: sql sql-server stored-procedures


    【解决方案1】:

    你是对的。基本上,SQL 将尝试在 FROM 和 JOIN 部分的所有表中查找您要查找的字段“my_column”。但是,如果您碰巧在表 A 和表 B 中有一个“my_column”,那么您需要通过包含表名明确告诉它您正在寻找哪个“my_column”。如果您在那里也有冲突,那么这会沿着链向上到达 dbo 和 databasename。

    大多数情况下,您会发现人们不会显式调用列所在的表,除非他们连接多个表。

    例如我这样写我的查询:

    SELECT a.field1, b.field2
    FROM tableA AS a
    INNER JOIN tableB AS b ON a.id = b.a_id
    WHERE a.id = 123
    

    在这里,我使用 AS 将 tableA 和 tableB 别名为更具可读性的 a 和 b。我可以像这样轻松地编写我的查询:

    SELECT tableA.field1, tableB.field2
    FROM tableA
    INNER JOIN tableB ON tableA.id = tableB.a_id
    WHERE tableA.id = 123
    

    或者像这样,如果 field1 和 field2 对那里的表来说是唯一的,但这对于每条数据的来源会有点混乱。

    SELECT field1, field2
    FROM tableA
    INNER JOIN tableB ON tableA.id = tableB.a_id
    WHERE tableA.id = 123
    

    【讨论】:

    • 我不能不同意这一点。使用表别名肯定有助于减少混乱,并且仍然提供必要的提示,通过单独查看查询来判断字段来自哪个表。 +1 给你。
    【解决方案2】:

    SQL Server 有四个部分名称:

    • 大多数情况下,您通过名称引用对象

      SELECT * FROM MyTable
      
    • 然后您可以指定对象的所有者或架构:

      SELECT * FROM dbo.MyTable
      
    • 然后就可以引用对象所在的数据库了:

      SELECT * FROM master.dbo.MyTble
      
    • 最后你可以在不同的服务器上引用表

      SELECT * FROM test1.master.dbo.MyTable
      

    比我在MSDN上的解释更好

    【讨论】:

    【解决方案3】:

    虽然可以为列使用隐含名称,但从可维护性方面来看,这是一个糟糕的选择。我从来没有把不会对每一列都设置别名的生产代码放出来,因为当你一年后回过头来更改那个报告或查询时,你真的不想弄清楚你加入的 20 个表中的哪一个此外,不指定会使数据库更难找到该列,并且在没有引用的情况下,两个表中的列名相同时,您会编写更多错误。使用显式引用是一个好习惯。

    【讨论】:

      【解决方案4】:

      多元化是错误的。

      以使用完全限定名称的存储过程为例,该名称引用同一数据库中的对象,以下还有两个不以这种方式完全限定的原因:

      • 如果您有一个引用同一数据库中的对象的存储过程,如果您重命名数据库,它将中断。

      • 如果您开始使用 Visual Studio 数据库工具将数据库脚本添加到源代码管理中,您会收到很多警告

      正确理解和利用模式是个好主意

      【讨论】:

        【解决方案5】:

        对象可以通过一个或多个标识符来引用。

        您可以使用单个标识符来引用一个对象,但如果标识符不明确,则必须使用更多标识符来唯一标识该对象。

        例如,存在于不同架构中的两个名为 TableA 的表必须在查询中使用至少两个标识符 schema_one.TableAschema_two.TableA 进行引用。

        有一个MDSN page,您可以在其中找到有关对象名称和标识符的更多信息。

        关于对象名称的多个标识符的使用,如果您更具体,可以减少查询中的歧义并加快查询的解析,因为数据库引擎不必解决歧义问题,但代价是查询的可读性。

        我个人的偏好(对于最常用的对象)是在引用表时使用schema.Table,如果在查询中引用单个表,则使用column,如果在查询中引用多个表,则使用table.column

        【讨论】:

          【解决方案6】:

          我认为这是主观问题之一,并且最终会成为一个偏好问题,但是:

          从可读性的角度来看,我主张仅在必要时才明确。 SQL 语句通常足够复杂,无需阅读大量不必要的文本。

          我认为

          SELECT TOP 1000 [StoreNumber]
                ,[Address1]
                ,[Address2]
                ,[City]
                ,[St]
                ,[Zip]
                ,[ZipSuffix]
                ,[LocationType]
                ,[LocationSubType]
                ,[Corp]
                ,[Division]
                ,[ZoneNumber]
                ,[DistrictNumber]
                ,[StateNumber] 
            FROM [CommonData].[dbo].[vw_StoreData]
          

          更具可读性
          SELECT TOP 1000 [CommonData].[dbo].[vw_StoreData].[StoreNumber]
                ,[CommonData].[dbo].[vw_StoreData].[[Address1]
                ,[CommonData].[dbo].[vw_StoreData].[[Address2]
                ,[CommonData].[dbo].[vw_StoreData].[[City]
                ,[CommonData].[dbo].[vw_StoreData].[[St]
                ,[CommonData].[dbo].[vw_StoreData].[[Zip]
                ,[CommonData].[dbo].[vw_StoreData].[[ZipSuffix]
                ,[CommonData].[dbo].[vw_StoreData].[[LocationType]
                ,[CommonData].[dbo].[vw_StoreData].[[LocationSubType]
                ,[CommonData].[dbo].[vw_StoreData].[[Corp]
                ,[CommonData].[dbo].[vw_StoreData].[[Division]
                ,[CommonData].[dbo].[vw_StoreData].[[ZoneNumber]
                ,[CommonData].[dbo].[vw_StoreData].[[DistrictNumber]
                ,[CommonData].[dbo].[vw_StoreData].[[StateNumber] 
            FROM [CommonData].[dbo].[vw_StoreData]
          

          (当您开始联接表时会变得更糟,如果您要跨不同数据库联接表,情况会更糟。)

          我可以看出您在哪里可以争辩说第二个更具可读性如果您需要通过查看来确切知道特定字段来自哪个数据库、架构和表仅在查询中。

          但在 SQL Server 中,例如,您可以在设计器中打开该查询,并以更友好的图形视图查看它。

          恕我直言,我唯一会使用完整语法的情况是必要时、跨越表/数据库/模式边界时,或者如果您有两个表具有相同的字段名称。

          例子:

          SELECT TOP 1000 [CommonData].[dbo].[vw_StoreData].[StoreNumber]
                ,[Address1]
                ,[Address2]
                ,[City]
                ,[St]
                ,[Zip]
                ,[ZipSuffix]
                ,[LocationType]
                ,[LocationSubType]
                ,[Corp]
                ,[Division]
                ,[ZoneNumber]
                ,[DistrictNumber]
                ,[StateNumber] 
            FROM [CommonData].[dbo].[vw_StoreData]
            Inner Join [CommonData].[dbo].[vw_StorePhones]
             ON [CommonData].[dbo].[vw_StorePhones].[StoreNumber] = [CommonData].[dbo].[vw_StoreData].[StoreNumber]
          

          即使在这种情况下,我也会使用 Table Aliases 来缩短它并使其更具可读性。

          综上所述,在现实世界中,您很可能会发现自己为一家已经确定了标准格式的公司工作,并且您需要根据该公司的标准进行编码。

          【讨论】:

          • 这就是为什么我说这是主观的和偏好的问题。 ;-)
          【解决方案7】:

          在大多数情况下,为了安全起见,我总是建议使用完整地址

              [databasename].[dbo].[some_table].[sometimesacolumngoeshere]
          

          但是,只有当您有多个数据库时才真正需要这样做。我只遇到过一两个选择数据库的问题,通常可以通过在 sql server 中选择正确的来解决。

          一旦您实际在查询中并且为表指定了一个缩短的别名,那么实际上就不需要包含完整地址,因为它已经被引用了。

          E.G

             FROM [databasename].[dbo].[some_table].[sometimesacolumngoeshere] SOME
          
             SELECT SOME.Name
          

          【讨论】:

            猜你喜欢
            • 2017-10-28
            • 2018-11-14
            • 1970-01-01
            • 1970-01-01
            • 2013-01-12
            • 2017-02-13
            • 2015-09-13
            • 1970-01-01
            相关资源
            最近更新 更多