7

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

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

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

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

my_column    or    [my_column]

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

你怎么知道什么时候使用一个而不是另一个合适,你怎么称呼这个,寻址?

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

4

7 回答 7

6

你是对的。基本上,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
于 2012-04-05T17:03:37.777 回答
2

SQL Server 有四个部分名称:

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

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

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

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

    SELECT * FROM test1.master.dbo.MyTable
    

它比我在MSDN上的解释更好

于 2012-04-05T16:59:53.643 回答
2

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

于 2012-04-05T17:06:08.260 回答
2

复视是错误的。

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

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

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

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

于 2016-02-14T23:08:08.317 回答
1

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

从可读性的角度来看,我主张仅在必要时才明确。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]

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

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

于 2012-04-05T17:00:41.037 回答
1

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

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

例如,TableA在查询中必须使用至少两个标识符schema_one.TableAschema_two.TableA.

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

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

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

于 2012-04-05T17:06:54.453 回答
0

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

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

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

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

例如

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

   SELECT SOME.Name
于 2017-09-14T09:28:20.720 回答