如何在SQL Server sql_variant类型中存储不同的排序规则文本?

时间:2019-04-05 13:37:49

标签: sql-server

SQL Server为每个sql_variant文本值存储自己的归类,因此我出于测试目的而尝试将德语到法语的字符串存储到sql_variant中。

CREATE TABLE [dbo].[VarCollation] 
(
    [uid] [INT] IDENTITY (1, 1) NOT NULL,
    [comment] NVARCHAR(100),
    [variant_ger] [sql_variant] NULL,
    [variant_rus] [sql_variant] NULL,
    [variant_jap] [sql_variant] NULL,
    [variant_ser] [sql_variant] NULL,
    [variant_kor] [sql_variant] NULL,
    [variant_fre] [sql_variant] NULL
) ON [PRIMARY]
GO

INSERT INTO VarCollation(comment, variant_ger, variant_rus, variant_jap, variant_ser, variant_kor, variant_fre) 
VALUES('NVarChar', 
       CONVERT(NVARCHAR, N'Öl fließt') COLLATE SQL_Latin1_General_CP1_CI_AS,
       CONVERT(NVARCHAR, N'Москва') COLLATE Cyrillic_General_CI_AS,
       CONVERT(NVARCHAR, N' ♪リンゴ可愛いや可愛いやリンゴ。半世紀も前に流行した「リンゴの') COLLATE Japanese_CI_AS,
       CONVERT(NVARCHAR, N'ŠšĐđČčĆ掞') COLLATE Serbian_Latin_100_CI_AS,
       CONVERT(NVARCHAR, N'향찰/鄕札 구결/口訣 이두/吏讀') COLLATE Korean_100_CI_AS,
       CONVERT(NVARCHAR, N'le caractère') COLLATE French_CS_AS);
GO

INSERT INTO VarCollation (comment, variant_ger, variant_rus, variant_jap, variant_ser, variant_kor, variant_fre) 
VALUES('VarChar', 
       CONVERT(VARCHAR, N'Öl fließt') COLLATE SQL_Latin1_General_CP1_CI_AS,
       CONVERT(VARCHAR, N'Москва') COLLATE Cyrillic_General_CI_AS,
       CONVERT(VARCHAR, N' ♪リンゴ可愛いや可愛いやリンゴ。半世紀も前に流行した「リンゴの') COLLATE Japanese_CI_AS,
       CONVERT(VARCHAR, N'ŠšĐđČčĆ掞') COLLATE Serbian_Latin_100_CI_AS,
       CONVERT(VARCHAR, N'향찰/鄕札 구결/口訣 이두/吏讀') COLLATE Korean_100_CI_AS,
       CONVERT(VARCHAR, N'le caractère') COLLATE French_CS_AS);
GO

通过分析每个sql_variant的数据,我看到存储的每个值都为NVARCHAR和VARCHAR分配了精确的排序规则。

German
collationId 0x3400d008
codepage    0x000004e4

Russian
collationId 0x0000d015
codepage    0x000004e3

Japanese
collationId 0x0000d010
codepage    0x000003a4

Serbian
collationId 0x0004d04c
codepage    0x000004e2

Korean
collationId 0x0004d040
codepage    0x000003b5

French
collationId 0x0000c00b
codepage    0x000004e4

但是SSMS会显示NVARCHAR的正确值,并显示VARCHAR的垃圾值

uid comment variant_ger variant_rus variant_jap variant_ser variant_kor variant_fre
1   NVarChar    Öl fließt   Москва   ♪リンゴ可愛いや可愛いやリンゴ。半世紀も前に流行した「リン  ŠšĐđČčĆ掞  향찰/鄕札 구결/口訣 이두/吏讀   le caractère
2   VarChar Ol flie?t   Москва  ?d????????????????????????????  SsDdCcCcZz  ??/?? ??/?? ??/??   le caractere

从我在sql_variant数据中看到的VARCHAR日语文本存储的某些字符已被0x3f('?')替换。我尝试在没有convertN的情况下插入,但结果相同。是否可以将此类文本插入sql_variant以及如何做到?

1 个答案:

答案 0 :(得分:1)

是的,要回答您的问题,可以在sql_variant中存储不同的排序规则,但是您的COLLATE语句放置在错误的位置。在nvarchar转换为varchar之后,您正在更改值 的排序规则,因此字符已经丢失。将varchar转换回nvarchar或事后更改排序规则不会恢复“丢失”的数据;它已经丢失了。

即使您修复了该问题,您也会注意到,但是您没有得到想要的结果:

USE Sandbox;
GO

CREATE TABLE TestT (TheVarchar sql_variant)
INSERT INTO dbo.TestT (TheVarchar)
SELECT CONVERT(varchar, N'향찰/鄕札 구결/口訣 이두/吏讀' COLLATE Korean_100_CI_AS)
INSERT INTO dbo.TestT (TheVarchar)
SELECT CONVERT(varchar, N' ♪リンゴ可愛いや可愛いやリンゴ。半世紀も前に流行した「リンゴの' COLLATE Japanese_CI_AS);

SELECT *
FROM dbo.TestT;
GO

DROP TABLE dbo.TestT;

请注意,第二个字符串的值为' ♪リンゴ可愛いや可愛いやリン'(已被截断)。这是因为您尚未声明varchar的长度值。 总是声明您的长度,精度,比例等。您比我更了解您的数据,因此您会知道一个合适的值。