Luk*_*til 6 sql-server collation sql-variant-property
我发现下面的查询在运行相同兼容性级别、相同设置选项等的两个 Azure 超大规模数据库上返回不同的结果。
IF CAST(ServerProperty('Edition') AS nvarchar(128)) = 'SQL Azure' BEGIN
SELECT 1
END
IF ServerProperty('Edition') = 'SQL Azure' BEGIN
SELECT 2
END
IF 'SQL Azure' = ServerProperty('Edition') BEGIN
SELECT 3
END
Run Code Online (Sandbox Code Playgroud)
在一个数据库上,它仅返回 1,在其他数据库上,它返回 1,2 和 3。
我调查了根本原因,似乎是由数据库的排序规则不同引起的。
对于以下查询:
SELECT SQL_VARIANT_PROPERTY(ServerProperty('Edition'), 'Collation')
SELECT name, collation_name, compatibility_level FROM sys.databases
Run Code Online (Sandbox Code Playgroud)
数据库只返回一行,结果是:
-----------------------------
SQL_Latin1_General_CP1_CI_AS
name collation_name compatibility_level
------------ -------------------------------- -------------------
master SQL_Latin1_General_CP1_CI_AS 140
my_database SQL_Latin1_General_CP850_CI_AS 150
Run Code Online (Sandbox Code Playgroud)
数据库返回1,2,3的结果是:
-----------------------------
SQL_Latin1_General_CP1_CI_AS
name collation_name compatibility_level
------------ -------------------------------- -------------------
master SQL_Latin1_General_CP1_CI_AS 140
my_database SQL_Latin1_General_CP1_CI_AS 150
Run Code Online (Sandbox Code Playgroud)
因此,不进行强制转换的简单比较是sql_variant与varchar(当我使用时没有区别N'SQL Azure')进行比较,其中底层的nvarchar排序sql_variant规则在一种情况下与我查询的数据库不同,而在其他情况下它是匹配的。
首先,我假设具有不同排序规则的两个字符串的比较会失败,就像尝试连接具有不同排序规则的两列时失败一样,但这里显然不是这种情况。
无论如何,安全比较函数输出的最佳方法是sql_variant什么varchar?
该类型位于数据优先级层次结构的顶部,因此在比较发生之前sql_variant会隐式转换为字符串文字。sql_variant
比较规则包括(sql_variant强调):
\n\n\n
\n- 当比较不同基本数据类型的 sql_variant 值并且基本数据类型属于不同数据类型系列时,层次结构图中数据类型系列较高的值被视为两个值中较大的一个。
\n- 当比较不同基本数据类型的 sql_variant 值并且基本数据类型属于同一数据类型族时,层次结构图中基本数据类型较低的值将隐式转换为其他数据类型,然后进行比较。
\n- 当比较 char、varchar、nchar 或 nvarchar 数据类型的 sql_variant 值时,首先根据以下条件比较它们的排序规则:LCID、LCID 版本、比较标志和排序 ID。每个标准都作为整数值进行比较,并按列出的顺序进行比较。如果所有这些条件都相等,则根据排序规则比较实际的字符串值。
\n
这解释了您看到的结果。
\n此外:
\n\n\n处理 sql_variant 数据类型时,SQL Server 支持将其他数据类型的对象隐式转换为 sql_variant 类型。但是,SQL Server 不支持从 sql_variant 数据到其他数据类型的对象的隐式转换。
\n
排序规则优先级的规则是单独的。它们在比较具有不同排序规则标签的字符串时适用。有关Coercible-default、Implicit X、Explicit X和No-collation标签的详细信息,请参阅链接文档。
\n使用当前数据库的排序规则将返回值转换sql_variant为基本类型。这将匹配分配给文字值的排序规则,该排序规则应具有 N 前缀才能解释为 Unicode。
就我而言,这意味着:
\nIF CONVERT(nvarchar(128), SERVERPROPERTY(\'Edition\')) COLLATE DATABASE_DEFAULT = \n N\'Developer Edition (64-bit)\'\nRun Code Online (Sandbox Code Playgroud)\n如果您完全按照预期提供字符串文字,则该子句COLLATE并不是绝对必要的,但您确实要求“最佳”方式,我认为这意味着“最全面”。
我的捷克朋友 Tom\xc3\xa1\xc5\xa1 Z\xc3\xadka 在Expecting Subvertations中写了有关此问题和相关问题的文章。
\n| 归档时间: |
|
| 查看次数: |
737 次 |
| 最近记录: |