跨服务器关联sys.columns表返回空集,求原因及解决办法
嘿,这个问题我之前踩过坑!核心是OBJECT_NAME()函数的上下文依赖特性在搞鬼,导致你的关联条件根本没生效:
当你写OBJECT_NAME(t.[object_id])的时候,这个函数默认会在你当前执行查询的数据库里查找对象名,而不是t所在的server1.db1库!同理,OBJECT_NAME(s.[object_id])也是在当前库找,不是server2.db2的对象——哪怕两边都有commonTable,函数返回的结果也对不上,自然就返回空集了。
给你两个靠谱的解决办法:
办法1:给OBJECT_NAME指定数据库ID
OBJECT_NAME()其实支持第二个参数,用来指定要查询的数据库ID。你可以用DB_ID()函数直接获取目标库的ID,这样就能精准解析对应库的对象名了:
SELECT * FROM server1.db1.sys.columns t INNER JOIN server2.db2.sys.columns s ON OBJECT_NAME(t.[object_id], DB_ID('server1.db1')) = OBJECT_NAME(s.[object_id], DB_ID('server2.db2')) AND t.name = s.name WHERE OBJECT_NAME(t.[object_id], DB_ID('server1.db1')) = 'commonTable';
办法2:直接关联sys.objects表(更推荐)
比起依赖OBJECT_NAME,直接关联各自库的sys.objects表来获取表名更稳妥,完全不会受上下文影响,性能也更好:
SELECT t.*, s.* FROM server1.db1.sys.columns t JOIN server1.db1.sys.objects ot ON t.object_id = ot.object_id JOIN server2.db2.sys.columns s JOIN server2.db2.sys.objects os ON s.object_id = os.object_id ON ot.name = os.name AND t.name = s.name WHERE ot.name = 'commonTable';
这个写法直接从对应数据库的元数据表中拿表名,逻辑清晰,也不容易出问题,是跨库/跨服务器查元数据的最佳实践。
最后提两个小注意点:
- 确保你的账号对两台服务器的两个数据库都有
VIEW DEFINITION权限,不然没法访问这些系统视图。 - 如果是第一次连这两台服务器,确认已经正确配置了链接服务器,不然会连不上server2哦。
内容的提问来源于stack exchange,提问作者Eric Klaus
相关产品推荐
相关产品推荐

