如何向SQL_Latin1_General_CP1_CI_AS排序规则的varchar列插入波兰字符
解决SQL Server varchar列(SQL_Latin1_General_CP1_CI_AS排序规则)插入波兰字符的问题
问题原因
SQL_Latin1_General_CP1_CI_AS排序规则绑定的是**ISO 8859-1(代码页1)**编码,该编码不包含ś等波兰语特殊字符。直接插入这些字符时,SQL Server会将无法识别的字符替换为?,这也是你尝试的几种方法无效的核心原因:
- 直接插入
'śmieci':客户端字符编码转换为ISO 8859-1时,特殊字符丢失 - 使用
COLLATE Polish_CI_AS:排序规则仅影响字符比较逻辑,不会改变列的底层编码,无法解决存储问题 - 插入
N'śmieci':nvarchar转varchar时,会自动适配列的ISO 8859-1编码,特殊字符被替换 CONVERT(nvarchar(255),'śmieci'):原字符串已因编码转换损坏,转nvarchar也无法恢复
无需修改列排序规则的解决办法
方法1:二进制中转存储
利用varbinary作为中转,将nvarchar格式的波兰字符转换为二进制字节存入varchar列,读取时再转换回nvarchar:
-- 测试插入 drop table if exists #MyTable create table #MyTable (MyColumn varchar(255) collate SQL_Latin1_General_CP1_CI_AS) -- 插入波兰字符(二进制中转) insert into #MyTable (MyColumn) select CONVERT(varchar(255), CONVERT(varbinary(255), N'śmieci')) -- 读取并还原字符 select CONVERT(nvarchar(255), CONVERT(varbinary(255), MyColumn)) as MyColumn from #MyTable
方法2:Base64编码存储
将波兰字符转换为Base64编码(纯ASCII字符,兼容ISO 8859-1),读取时解码还原:
-- 测试插入 drop table if exists #MyTable create table #MyTable (MyColumn varchar(255) collate SQL_Latin1_General_CP1_CI_AS) -- 插入Base64编码的波兰字符 insert into #MyTable (MyColumn) select CAST(N'' AS XML).value('xs:base64Binary(xs:hexBinary(sql:column("bin")))', 'varchar(255)') from (select CONVERT(varbinary(255), N'śmieci') as bin) as t -- 读取并解码还原 select CAST(N'' AS XML).value('xs:base64Binary(sql:column("MyColumn"))', 'nvarchar(255)') as MyColumn from #MyTable
注意事项
- 两种方法都需要在插入和读取时做对应的转换操作,无法直接通过
SELECT MyColumn得到原始字符 - 若后续有大量这类需求,长期来看修改列类型为
nvarchar(无需重建表,可在线修改)是更优的方案
内容的提问来源于stack exchange,提问作者Arkadiusz
相关产品推荐
相关产品推荐

