SQL Server中用于寻址表的正确语法是什么?

时间:2012-04-05 16:53:31

标签: sql sql-server stored-procedures

这似乎是一个相当明显的问题,但我无法想到我想要问的正确用语,所以提出这方面的参考资料一直很棘手。但答案显而易见。

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

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

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

my_column    or    [my_column]

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

你怎么知道何时使用一个而不是另一个,你也称之为解决这个问题?

我的偏好是永远是明确的,如果你需要节省空间和/或使事情更清楚,你可以使用一个明确的完整“地址”别名,对吗?

7 个答案:

答案 0 :(得分: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

答案 1 :(得分:2)

SQL Server有四个部分名称:

  • 通常您按名称引用对象

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

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

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

    SELECT * FROM test1.master.dbo.MyTable
    

MSDN

上解释得比我好

答案 2 :(得分:2)

虽然可以对列使用隐含名称,但从可维护性方面来看,它是一个糟糕的选择。我从来没有把生产代码排除在每个列的别名之外,因为当你一年后回去改变那个报告或查询时,你真的不想弄清楚你加入的那20个表中的哪一个此外,未指定会使数据库更难以找到列,并且如果在没有引用的情况下两个表中的列名相同,则会编码更多错误。使用明确的引用是一个好习惯。

答案 3 :(得分:2)

Pluralsight错了。

给出使用引用同一数据库中对象的完全限定名称的存储过程的示例,以下是另外两个不能以这种方式完全限定的原因:

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

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

理解并正确使用架构

是个好主意

答案 4 :(得分: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]

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

所有这一切都表明,在现实世界中,您很可能会发现自己在为已经决定标准格式的公司工作,并且您需要根据公司的标准进行编码。

答案 5 :(得分:1)

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

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

例如,必须使用至少两个标识符TableAschema_one.TableA在查询中引用存在于不同模式中的两个名为schema_two.TableA的表。

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

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

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

答案 6 :(得分:0)

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

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

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

一旦你实际进入查询并且你给了表一个缩短的别名,那么实际上不需要包含完整的地址,因为这已经被引用了。

E.G

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

   SELECT SOME.Name