【问题标题】:Using multipart column identifiers使用多部分列标识符
【发布时间】:2019-10-29 11:09:59
【问题描述】:

我确信这必须在某处记录,但在我的一生中,我似乎无法找到任何解释该行为的实际文档。

采取4种方式来引用表格(我不相信还有更多但请随时纠正我):

  1. 当前数据库
  2. 远程数据库
  3. 链接服务器
  4. 同义词

他们在使用多部分列标识符时的行为似乎有所不同,我试图了解其背后的原因。我已经测试了各种类型的SELECT 语句:

当前数据库

作品

SELECT Column FROM Schema.Table;
SELECT Table.Column FROM Schema.Table;
SELECT Schema.Table.Column FROM Schema.Table;
SELECT Alias.Column FROM Schema.Table AS Alias;

即使这样也行! (显然仅在使用 dbo Schema 时,但仍然如此)

SELECT Schema.Table.Column FROM Table;

远程数据库

作品

SELECT Column FROM RemoteDB.Schema.Table;
SELECT Table.Column FROM RemoteDB.Schema.Table;
SELECT RemoteDB.Schema.Table.Column FROM RemoteDB.Schema.Table;
SELECT Alias.Column FROM RemoteDB.Schema.Table AS Alias;

失败

SELECT Schema.Table.Column FROM RemoteDB.Schema.Table;
The multi-part identifier "Schema.Table.Column" could not be bound.

链接服务器

作品

SELECT Column FROM LinkedServer.RemoteDB.Schema.Table;
SELECT Table.Column FROM LinkedServer.RemoteDB.Schema.Table;
SELECT Alias.Column FROM LinkedServer.RemoteDB.Schema.Table AS Alias;

失败

SELECT Schema.Table.Column FROM LinkedServer.RemoteDB.Schema.Table;
The multi-part identifier "Schema.Table.Column" could not be bound.

SELECT RemoteDB.Schema.Table.Column FROM LinkedServer.RemoteDB.Schema.Table;
The multi-part identifier "RemoteDB.Schema.Table.Column" could not be bound.

SELECT LinkedServer.RemoteDB.Schema.Table.Column FROM LinkedServer.RemoteDB.Schema.Table;
The multi-part identifier "LinkedServer.RemoteDB.Schema.Table.Column" could not be bound.
**I believe this fails are you're only allowed a maximum of 4 parts in the identifier?**
**Read this somewhere but nothing authoritive.  Would appreciate a reference.**

同义词

作品

SELECT Column FROM SynonymName;
SELECT Column FROM SynonymSchema.SynonymName;
SELECT SynonymName.ColumnName FROM SynonymSchema.SynonymName;
SELECT SynonymSchema.SynonymName.Column FROM SynonymSchema.SynonymName;
SELECT Alias.Column FROM SynonymSchema.SynonymName AS Alias;

即使这样也行! (显然仅在使用 dbo Schema 时,但仍然如此)

SELECT SynonymSchema.SynonymName.Column FROM SynonymName;
  1. 我试图了解为什么某些多部分标识符在以一种方式使用(例如针对本地数据库的架构)时有效,但在以另一种方式使用时会失败(例如针对远程数据库/链接服务器的架构)。
  2. 您是否应该始终使用别名来确保一切正常?

任何建议都将受到高度赞赏,特别是有关“一刀切”场景的设计背后的原因和最佳实践建议的官方文档的指针(我目前推测这是别名路线) .

【问题讨论】:

  • 永远不要在SELECT 中对列名使用三部分(+)命名。不推荐使用像 SELECT dbo.MyTable.MyColumn FROM dbo.MyTable; 这样的语法,并且您的 SQL 将在未来的某一天失败。如果您要引用特定表中的列,最好的方法是为该表添加别名,然后在该列前面加上该别名:SELECT MT.MyColumn FROM dbo.MyTable MT;。唯一一次您希望看到 3 部分 + 列的命名是在使用 sp_rename 时,因为它是必需的,这是因为列的名称是字符串文字参数。
  • @Larnu:谢谢你,请问你有任何关于弃用的文档链接吗?我觉得仅此一项就可以提供相当多的见解..
  • Deprecated Database Engine Features in SQL Server 2017:在“三部分和四部分列引用”下。。我不记得它被添加到弃用列表中的版本
  • 太棒了,谢谢,这绝对是无价之宝。

标签: sql-server tsql sql-server-2016


【解决方案1】:

最佳实践 - 为您的表命名并为列名使用两部分标识符 - 第一部分是表别名,第二部分是列名。

为什么?因为:

  • 一旦查询包含连接(或应用),并且该列名恰好属于多个表,使用单个部分标识符就会中断。

  • 对列使用两个以上的部分标识符将强制您将大部分标识符写入两次 - 一次用于列,一次用于表。如果有任何变化(例如表移动到不同的架构、链接服务器名称更改、同义词更改),您现在必须在(至少)两个地方更改查询。

  • 对列使用两部分标识符意味着您确切知道该列属于哪个表,即使您添加了 join/apply 子句,或者只是将具有相同名称的列添加到现有的一个查询中的表,您根本不需要更改查询。此外,您现在只有一个位置可以确定表格的来源。

  • 对于 cmets 中的链接,不推荐使用三或四部分的列标识符(感谢 @larnu)。

最重要的是 - 列属于表。它们不属于服务器、数据库或模式。

请注意,此答案中的表一词可与视图、表值函数、表变量等互换。

【讨论】:

  • 很高兴为您提供帮助 :-)
猜你喜欢
  • 1970-01-01
  • 2020-06-16
  • 1970-01-01
  • 2011-01-06
  • 2011-11-10
  • 2016-10-28
  • 2010-11-02
相关资源
最近更新 更多