SQL Server 中是否有任何方法可以确定代码页中的字符代表什么,而无需实际创建该排序规则的测试数据库?
示例。如果我使用排序规则
SQL_Ukrainian_CP1251_CS_AS
创建测试数据库,然后执行 CHAR(255)
,它将返回 я
。
如果我在具有
SQL_Latin1_General_CP1_CS_AS
排序规则的数据库上尝试以下操作
SELECT CHAR(255) COLLATE SQL_Ukrainian_CP1251_CS_AS
它返回
y
SELECT CHAR(255)
返回
ÿ
,因此它显然首先通过数据库的默认排序规则,然后尝试找到与显式排序规则中最接近的等效项。这可以避免吗?
实际上有一种相当直接的方法可以做到这一点
SELECT CONCAT(CAST(255 AS BINARY(1)), '' COLLATE SQL_Ukrainian_CP1251_CS_AS)
因此,基于此方法,SQL Server 2022+ 兼容脚本可为正在使用的所有 16 个非 utf8 代码页返回从
0x01
到 0xFF
的 255 个值 (DB Fiddle)。
DECLARE @DynSQL NVARCHAR(MAX);
WITH DistinctCodePage AS
(
SELECT CodePage = CAST(COLLATIONPROPERTY(name, 'CodePage') AS INT),
ExampleCollation = MAX(name)
FROM sys.fn_helpcollations()
WHERE COLLATIONPROPERTY(name, 'CodePage') NOT IN (0 /*Exclude Unicode only collations*/, 65001 /*Exclude utf8 collations*/)
GROUP BY COLLATIONPROPERTY(name, 'CodePage')
)
SELECT @DynSQL = 'SELECT value,' +
STRING_AGG(CONVERT(NVARCHAR(MAX), quotename(CodePage) + ' = CONCAT(CAST(value AS binary(1)), SPACE(0) COLLATE ' + ExampleCollation + ')' ), ',') +
'
FROM generate_series(1,255)
ORDER BY value desc'
FROM DistinctCodePage;
EXEC (@DynSQL);
虽然 MS SQL 同时支持代码页和 Unicode,但它不提供任何在两者之间进行转换的函数,因此弄清楚不同代码页中的值代表什么字符是一件很困难的事情。
我见过两种可能的方法来处理转换,其中一种详细信息请参见此处 http://www.codeguru.com/cpp/data/data-misc/values/article.php/c4571 并涉及将自定义转换程序连接到数据库并使用它进行转换。
另一种是构建一个数据库表,其中包括
[CodePage], [ANSI Value], [UnicodeValue]
将 unicode 值存储为表示要使用
nchar()
转换的 unicode 字符的 int 或 nchar 本身
您使用的排序规则
SQL_Ukrainian_CP1251_CS_AS
是代码页1251(从字符串中心开始的CP1251)。您可以在此处获取其翻译表http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT
它是一个 TSV,因此在修剪顶部后,原始数据应该相当干净地导入。
就我个人而言,我更倾向于后者而不是前者,特别是对于生产服务器,因为前者可能会带来不稳定。