为什么在某些情况下不替换 Unicode 字符?

Ril*_*jor 4 sql-server collation t-sql unicode

正如预期的那样,在“测试”中运行此结果:

SELECT
    REPLACE(NCHAR(1234), NCHAR(1234), N'test');
Run Code Online (Sandbox Code Playgroud)

但是,运行此结果会生成“a?a”,其中没有“test”:

SELECT
    REPLACE(N'a' + NCHAR(1234) + N'a', NCHAR(1234), N'test');
Run Code Online (Sandbox Code Playgroud)

我认为这可能与 haystack 而不是针的字符串连接有关,但是当我尝试这样做时,它仍然没有“工作”:

SELECT
    REPLACE(N'a' + NCHAR(1234) + N'a', N'' + NCHAR(1234) + N'', N'test');
Run Code Online (Sandbox Code Playgroud)

结果:“a?a”

我怀疑这可能与它如何解释字符有关,所以我尝试指定一个二进制排序规则......并“修复”了这个问题:

SELECT
    REPLACE(N'a' + NCHAR(1234) + N'a' COLLATE Latin1_General_100_BIN2, NCHAR(1234), N'test');
Run Code Online (Sandbox Code Playgroud)

结果:“atesta”。

为什么?

这种行为似乎对某些角色存在,但对其他角色不存在。

SELECT
    REPLACE(N'a' + NCHAR(23423) + N'a', NCHAR(23423), N'test');
Run Code Online (Sandbox Code Playgroud)

结果:“atesta”(“作品”)

SELECT
    REPLACE(N'a' + NCHAR(5342) + N'a', NCHAR(5342), N'test');
Run Code Online (Sandbox Code Playgroud)

结果:“a?a”(不“工作”)

为什么?

Sol*_*zky 6

这种行为仅仅是因为您在具有“100”之前系列默认排序规则的数据库中执行查询,在这种情况下,很多字符没有任何排序权重。没有排序权重意味着它们等同于空字符串。它们的值为 0。因此,当不涉及其他排序权重时,它们总是彼此相等。它们也等同于空字符串。版本 100 排序规则(从 SQL Server 2008 开始,版本 10.0 或 100 没有十进制/次要版本)为大多数字符添加了排序权重。因此,只需通过添加COLLATE Latin1_General_100_CI_AS_SC. 任何版本的二进制排序规则(以 结尾_BIN2,不要使用以 just 结尾的排序规则_BIN)也可以工作,因为二进制排序规则中没有排序权重之类的东西。

SELECT 1 WHERE NCHAR(1234) = '' COLLATE SQL_Latin1_General_CP1_CI_AS;
-- 1

SELECT 2 WHERE NCHAR(1234) = '' COLLATE Latin1_General_CI_AS;
-- 2

SELECT 3 WHERE NCHAR(1234) = '' COLLATE Latin1_General_100_CI_AS;
-- (no results)

SELECT 4 WHERE NCHAR(1234) = '' COLLATE Latin1_General_BIN2;
-- (no results)
Run Code Online (Sandbox Code Playgroud)

即使多个没有权重的字符仍然等同于空字符串(或任何没有排序权重的字符):

SELECT 5 WHERE NCHAR(1234) + NCHAR(1234) + NCHAR(1234)
       = N'' COLLATE Latin1_General_CS_AS_KS_WS;
-- 5
Run Code Online (Sandbox Code Playgroud)

在下一个测试中,NCHAR(1234)仅当使用版本 100(或更新的)排序规则时才等于自身。Pre-version 100 Collat​​ions 没有分配排序权重NCHAR(1234),因此它不等同于任何东西,因此以前在第一个表达式中找不到它。

SELECT REPLACE(N'a' + NCHAR(1234) + N'a',
               NCHAR(1234) COLLATE Latin1_General_100_CI_AS,
               N'test');
-- atesta
Run Code Online (Sandbox Code Playgroud)

继续上面的示例#5,我们可以证明 3 个没有权重的字符等同于 2 个也没有权重的不同字符:

SELECT 6 WHERE NCHAR(1234) + NCHAR(1234) + NCHAR(1234)
             = NCHAR(5342) + NCHAR(5342) COLLATE Latin1_General_CS_AS_KS_WS;
-- 6
Run Code Online (Sandbox Code Playgroud)

但是切换到版本 100 排序规则会改变:

SELECT 7 WHERE NCHAR(1234) + NCHAR(1234) + NCHAR(1234)
             = NCHAR(5342) + NCHAR(5342) COLLATE Latin1_General_100_CS_AS_KS_WS;
-- (no results)

SELECT 8 WHERE NCHAR(1234) = NCHAR(5342) COLLATE Latin1_General_100_CS_AS_KS_WS;
-- (no results)
Run Code Online (Sandbox Code Playgroud)

请参阅我以下帖子的“补充字符”字符部分。在该部分中,我展示了与补充字符相关的类似行为,在该部分的末尾,我展示了每个排序规则版本有多少 BMP 字符(即非补充字符)与这些“缺失权重”字符之一匹配。

统一代码:搜索 T-SQL 标识符的真实有效字符列表,第 3 部分,共 2 部分(分隔标识符)

有关使用 Collat​​ions 的更多信息,请访问:Collat​​ions.info