特定字符大小写组合引发SQL查询失败,如何在MSSQL中解决?
问题描述
当SQL查询的WHERE子句中列名出现小写字母a后跟大写字母A(aA)的组合时,会触发报错:Invalid column name 'DataAreaId'。示例如下:
-- 执行成功 select top 100 * from inventtable where DATAAREAID = 'a04' -- 执行成功 select top 100 * from inventtable where datAareaid = 'a04' -- 执行失败 select top 100 * from inventtable where dataAreaid = 'a04'
服务器、数据库、表及列的排序规则均为Danish_Norwegian_CI_AS,EF Core自动生成的含[DataAreaId]的查询也会因同样原因执行失败:
SELECT top (100) * FROM [InventTable] WHERE [DataAreaId] = 'a04'
目前已通过模型构建时将列映射为全大写规避问题,以下是对问题本质的分析及SQL端的解决办法:
问题本质
核心原因在于Danish_Norwegian_CI_AS排序规则的特殊字符处理逻辑:在丹麦-挪威语的排序规则中,字符串中的aa组合(无论大小写,包括aA、Aa)会被视为单个特殊字符å(挪威语字母)。
SQL Server解析标识符(列名、表名等)时,会遵循指定的排序规则进行匹配。当查询中的列名包含aA组合时,SQL Server会将该组合转换为å,导致标识符被解析为类似datåreaid的形式;而实际表中的列名是DATAAREAID(包含两个大写A),两者在该排序规则下无法匹配,最终触发“列名无效”的报错。
SQL端解决办法
1. 修改标识符排序规则
将数据库、表或列的排序规则改为不包含aa/å等价处理的规则(如SQL_Latin1_General_CP1_CI_AS)。标识符的排序规则默认由数据库排序规则决定,修改时需注意:
- 需备份数据后操作,避免影响现有业务的排序逻辑
- 修改数据库排序规则可能需要重建部分对象(如索引、视图)
2. 强制使用二进制排序规则匹配
在查询中对列名强制指定二进制排序规则,绕过aa/å的等价处理,示例:
SELECT top 100 * FROM inventtable WHERE inventtable.[dataAreaid] COLLATE Latin1_General_BIN = 'a04'
此方法无需修改全局排序规则,但需在每个涉及此类列的查询中手动指定,适合临时场景。
3. 统一标识符大小写
确保查询中的列名大小写与系统存储的完全一致(如实际列名是全大写DATAAREAID,查询时也使用全大写),结合方括号包裹标识符,可以避免排序规则的特殊处理干扰匹配逻辑。
内容的提问来源于stack exchange,提问作者Eric Ruder

