这似乎是一个相当明显的问题,但我无法想到我想要问的正确用语,所以提出这方面的参考资料一直很棘手。但答案显而易见。
在检查SQL Server的Pluralsight培训材料时,他们建议始终引用“常规”查询中的表(您可能为基本Web服务编写的内容)和可能存储过程中的SQL查询,如下所示:
[databasename].[dbo].[some_table].[sometimesacolumngoeshere]
虽然我发现遇到存储过程等非常常见,只需使用:
my_column or [my_column]
这里的区别显然是明确地提供了一个绝对的“地址”,而另一个是隐含的。
你怎么知道何时使用一个而不是另一个,你也称之为解决这个问题?
我的偏好是永远是明确的,如果你需要节省空间和/或使事情更清楚,你可以使用一个明确的完整“地址”别名,对吗?
答案 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)
可以通过一个或多个标识符引用对象。
您可以使用单个标识符来引用对象,但如果标识符不明确,则必须使用更多标识符来唯一标识该对象。
例如,必须使用至少两个标识符TableA
和schema_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