ODBC查询SQL Server列缺失:sp_columns与INFORMATION_SCHEMA.columns不匹配
问题背景
Linux环境下的Oracle 12.1通过dg4odbc及Linux版MS-SQLServer ODBC驱动连接Windows上的SQL Server,使用select * from schema.table@dblink查询SQL Server数据基本可行,但遇到以下异常:
- 执行
select * from INFORMATION_SCHEMA.columns where table_name = 'X'返回全部242列,但select * from X仅返回约64列,且所有domain_catalog列非空的字段均缺失,缺失无规律(存在带/不带domain_catalog值的bigint列)。 - 为排除Oracle接口问题,使用Linux上的Microsoft sqlcmd(版本11和18,搭配对应ODBC驱动)测试:执行
exec sp_columns BUV_BUCHUNGSVARIANTE仅返回2行,而select * from BUV_BUCHUNGSVARIANTE显示全部10列(仅涉及微软工具及ODBC驱动,无Oracle参与)。
问题1:为何select *会缺失domain_catalog非空的列?
这是因为ODBC驱动(尤其是旧版本的SQL Server ODBC驱动)在处理**用户自定义数据类型(UDT)**的元数据时存在缺陷。domain_catalog非空的列本质是基于用户自定义数据类型创建的,驱动在解析这类列的元数据时出错,导致Oracle dg4odbc或sqlcmd的sp_columns无法识别这些列;但直接执行select *时SQL Server本身能正常返回数据,只是驱动层过滤掉了这些列的元数据,最终表现为查询结果缺失列。
问题2:列级别上的domain_catalog含义是什么?
在SQL Server的INFORMATION_SCHEMA.columns中,domain_catalog表示用户自定义数据类型(UDT)所在的数据库名称。如果列使用的是系统内置数据类型(如int、varchar),该字段为空;只有当列使用用户自行创建的自定义数据类型时,该字段才会填充为该UDT所属的数据库名。
问题3:开发者为何会设计带/不带domain_catalog项的列?
- 使用系统内置数据类型(
domain_catalog为空):满足常规业务需求,内置类型兼容性好、性能稳定,无需额外维护,适合大多数通用场景。 - 使用用户自定义数据类型(
domain_catalog非空):主要为了统一数据格式和约束,比如多个表需要使用相同的编号规则(如固定长度的员工ID),可以创建自定义类型统一管理,避免重复设置约束;同时也能提升代码可读性,用有业务含义的类型名替代抽象的内置类型。
问题4:连接SQL Server的账号需具备哪些权限才能访问表的所有列?
要访问表的所有列,账号需要具备以下权限:
- 目标表的
SELECT权限:这是读取表数据的基础权限。 - 用户自定义数据类型(UDT)的
VIEW DEFINITION权限:因为domain_catalog非空的列依赖UDT,若无该权限,驱动无法获取UDT的元数据,会导致这类列被过滤。 - 若涉及跨数据库的UDT,还需要具备UDT所在数据库的
CONNECT权限,以及对该UDT的VIEW DEFINITION权限。
内容的提问来源于stack exchange,提问作者dipr
相关产品推荐
相关产品推荐

