SQL Server中CS_AS排序规则查询扩展属性结果异常
问题分析与解决
问题场景
存在两个SQL Server数据库:
- 数据库1:排序规则为
Latin1_General_CI_AI - 数据库2:排序规则为
Latin1_General_CS_AS
两者均配置了名为Version的扩展属性,值均为1。执行以下校验代码时:
IF ((SELECT value FROM sys.extended_properties WHERE name = 'Version') <> '1') BEGIN RAISERROR ('Wrong Version', 16, 1); END
仅数据库2返回Wrong Version错误,数据库1无报错,与预期不符。单独执行查询语句:
SELECT value FROM sys.extended_properties WHERE name = 'Version'
两个数据库均返回值1;尝试在查询中指定排序规则后问题仍未解决:
IF ((SELECT value FROM sys.extended_properties WHERE name = 'Version' collate Latin1_General_CI_AI) <> 1) BEGIN RAISERROR ('Wrong Version',16,1); END
问题原因
核心问题出在sys.extended_properties表的value列类型为sql_variant,该类型的比较逻辑特殊:
- 比较时会先校验操作数的基数据类型,再校验排序规则
- 在
CS_AS(区分大小写、区分重音)的严格排序规则下,sql_variant与字符串/数字常量的隐式转换会触发严格匹配逻辑,即使视觉上值相同,也可能因类型转换的细微差异导致比较结果为不等 - 直接在列上指定
COLLATE无法解决类型层面的隐式转换冲突
解决方案
解决思路是将sql_variant类型的value显式转换为明确的数据类型(如VARCHAR或INT)后再进行比较,避免隐式转换带来的问题:
方案1:转换为字符串类型比较
IF ((SELECT CAST(value AS VARCHAR(50)) FROM sys.extended_properties WHERE name = 'Version') <> '1') BEGIN RAISERROR ('Wrong Version', 16, 1); END
方案2:转换为整数类型比较
如果Version属性值确定为整数,可直接转换为INT:
IF ((SELECT CAST(value AS INT) FROM sys.extended_properties WHERE name = 'Version') <> 1) BEGIN RAISERROR ('Wrong Version', 16, 1); END
补充说明
若需要兼容多场景,也可使用CONVERT函数并指定样式,确保转换逻辑一致:
IF ((SELECT CONVERT(VARCHAR(50), value) FROM sys.extended_properties WHERE name = 'Version') <> '1') BEGIN RAISERROR ('Wrong Version', 16, 1); END
内容的提问来源于stack exchange,提问作者Arthur Quenneville
相关产品推荐
相关产品推荐

