如何在 SQL Server 中获取区分大小写的排序规则版本?

2023-12-05

有没有办法获得区分大小写的排序规则版本以在查询中使用?

假设该查询可用于具有不同排序规则的数据库,其中一些排序规则不区分大小写,并且可以具有不同的区域性。 (例如多个客户端)

但是,此查询应始终以区分大小写的方式运行,同时(如果可能)不更改排序规则区域性和其他属性。

例如,如果数据库恰好使用SQL_Latin1_General_CP1_CI_AS(这里的CI代表不区分大小写),我想使用SQL_Latin1_General_CP1_CS_AS(CS代表区分大小写)。

简单查询示例:

DECLARE @Title nvarchar(2) = 'qQ'

--Case insensitive (following DB collation)
SELECT REPLACE(@Title, 'q', 'o') --Result: 'oo'

--Case sensitive, but fixed to a collation
SELECT REPLACE(@Title COLLATE SQL_Latin1_General_CP1_CS_AS, 'q', 'o') --Result: 'oQ'

在查询中修复此类排序规则可能会在迁移代码或稍后更改数据库排序规则时导致问题。

是否有内置函数可以获取当前排序规则的区分大小写的版本,或者可以用于此目的的解决方法?


排序规则不一定由数据库默认值决定:它们也可以按字符串字段设置。

不,除了使用动态 SQL 编写之外,我从未见过(而且我也看过)进行动态排序的方法COLLATE子句放入查询中。或者,如果您需要考虑的选项数量相当少,您could也许尝试类似以下的方法:

SELECT ...
FROM   ...
WHERE (@CaseSensitive = 1 AND [Field] LIKE N'%' + @Name + N'%' COLLATE Something_CS_AS)
OR (@CaseSensitive = 0 AND [Field] LIKE N'%' + @Name + N'%')

另外,没有direct大小写(甚至重音、假名或宽度)敏感和不敏感之间的等效性。虽然大多数情况下,不区分大小写的排序规则都有对应的区分大小写的排序规则,但有 15 种排序规则是仅不区分大小写的:

;WITH CaseS AS
(
  SELECT [name]
  FROM   sys.fn_helpcollations()
  WHERE  [name] LIKE N'%[_]cs[_]%'
)
SELECT CaseI.*
FROM   sys.fn_helpcollations() CaseI
LEFT JOIN CaseS
       ON CaseI.name = REPLACE(CaseS.[name], N'_CS_', N'_CI_')
WHERE  CaseI.[name] LIKE N'%[_]ci[_]%'
AND    CaseS.[name] IS NULL;

Returns:

name                                  description
SQL_1xCompat_CP850_CI_AS              ...
SQL_AltDiction_CP850_CI_AI            ...
SQL_AltDiction_Pref_CP850_CI_AS       ...
SQL_Danish_Pref_CP1_CI_AS             ...
SQL_Icelandic_Pref_CP1_CI_AS          ...
SQL_Latin1_General_CP1_CI_AI          ...
SQL_Latin1_General_CP1253_CI_AI       ...
SQL_Latin1_General_CP437_CI_AI        ...
SQL_Latin1_General_CP850_CI_AI        ...
SQL_Latin1_General_Pref_CP1_CI_AS     ...
SQL_Latin1_General_Pref_CP437_CI_AS   ...
SQL_Latin1_General_Pref_CP850_CI_AS   ...
SQL_Scandinavian_Pref_CP850_CI_AS     ...
SQL_SwedishPhone_Pref_CP1_CI_AS       ...
SQL_SwedishStd_Pref_CP1_CI_AS         ...

在查询中修复这样的排序规则可能会在迁移代码时导致问题,

为什么?您打算将代码迁移到哪里?如果是另一个 RDBMS,那么您已经需要应对数据类型差异、SQL 方言差异、“最佳实践”差异等。那么为什么要担心排序规则呢?除非您确定要迁移到另一个 RDBMS,否则您应该充分利用当前平台,使您的系统尽可能最佳地工作,而不是由于以下原因而处于不太理想的状态:仅使用最低评论分母功能。

或稍后更改数据库排序规则。

你为什么要这样做?同样,具有显式 COLLATION 设置的任何字符串字段都不受数据库默认值的影响。


If you are looking for strict Case (and everything including Accent, etc) sensitivity on equivalence (we are not talking about range searches or sorting), then you can use a Binary collation (i.e. one ending in either _BIN or _BIN2). Just keep in mind that binary collations might not sort the way you might expect since they are not "dictionary" based sorts, at least not in terms of a single binary collation that would behave the same across all languages. They also don't make equivalences between languages (i.e. equating "a" with an "a" that has an accent).

自从最初发布这个答案以来,我发现上面的段落实际上是不好的建议。请这样做not如果目标是区分大小写,请使用二进制排序规则。它过于严格,在许多情况下不会给出准确的结果。详细信息和示例请参见:不,二进制排序规则不区分大小写.

另外,请做not使用以 just 结尾的二进制排序规则_BIN因为自 SQL Server 2005 发布以来它们已过时,并且仅应在需要保持与另一个也使用 SQL Server 的系统的向后兼容性时使用_BIN整理。如果您需要二进制排序规则,请使用以_BIN2。详细信息和示例请参见:各种二进制排序规则之间的差异(文化、版本以及 BIN 与 BIN2).


UPDATE

我能够想出一个函数来获取传入排序规则的区分大小写的版本(如果存在)。然而,此函数仅有助于创建正确的动态 SQL;它不能在查询中内联使用来动态设置 COLLATE 子句(主要是因为不能这样做)。有两个参数:

  • @CollationName-- 如果您传入此值,您将返回它的区分大小写的版本(如果存在)。这@DatabaseName参数将被忽略。
  • @DatabaseName-- 如果您不知道确切的排序规则,请离开@CollationName as NULL并将其传入,它将查找该数据库的默认排序规则。
  • 如果两个参数都是NULL然后它将查找该函数所在数据库的默认排序规则。
  • 如果传入或查找的排序规则已经区分大小写,则将返回该名称
  • 待办事项(当我有时间时):查找没有默认值的数据库的服务器默认排序规则(它们将有NULL作为他们的默认排序规则名称)

该函数有两个版本:第一个是 TVF(因为它们更快)和标量 UDF(因为它们有时更容易交互)。

表值函数:

USE [Test];
SET ANSI_NULLS ON;

IF (OBJECT_ID(N'dbo.GetCaseSensitiveCollation') IS NOT NULL)
BEGIN
  DROP FUNCTION dbo.GetCaseSensitiveCollation;
END;

GO
CREATE FUNCTION dbo.GetCaseSensitiveCollation
(
  @CollationName sysname,
  @DatabaseName sysname
)
RETURNS TABLE
--WITH SCHEMABINDING
--     Cannot schema bind table valued function 'dbo.GetCaseSensitiveCollation'
--     because it references system object 'sys.fn_helpcollations'.
AS RETURN

  WITH collation(name) AS
  (
    SELECT CONVERT(sysname, COALESCE(@CollationName,
                DATABASEPROPERTYEX(COALESCE(@DatabaseName, DB_NAME()), 'Collation')))
  )
  SELECT col.[name]
  FROM   sys.fn_helpcollations() col
  CROSS JOIN collation
  WHERE  col.[name] = CASE WHEN collation.[name] LIKE N'%[_]CS[_]%' 
                               THEN collation.[name]
                           ELSE REPLACE(collation.[name], N'_CI_', N'_CS_')
                      END;
GO

例子:

-- Get CS Collation for the specified Collation
SELECT [name] AS [BySpecificCollation]
FROM dbo.GetCaseSensitiveCollation(N'Indic_General_100_CI_AS_KS_WS', NULL);

-- Get CS Collation based on database default for the specified database
SELECT [name] AS [ByDefaultCollationForDB]
FROM dbo.GetCaseSensitiveCollation(NULL, N'msdb');

-- Get CS Collation based on database default for database that the function exists in
SELECT [name] AS [CurrentDB]
FROM Test.dbo.GetCaseSensitiveCollation(NULL, NULL);

-- Get CS Collation based on database default for the current database
USE [ReportServer];
SELECT [name] AS [CurrentDB]
FROM Test.dbo.GetCaseSensitiveCollation(NULL, DB_NAME());

标量用户定义函数:

USE [Test];
SET ANSI_NULLS ON;

IF (OBJECT_ID(N'dbo.GetCaseSensitiveCollation2') IS NOT NULL)
BEGIN
  DROP FUNCTION dbo.GetCaseSensitiveCollation2;
END;
GO
CREATE FUNCTION dbo.GetCaseSensitiveCollation2
(
  @CollationName sysname,
  @DatabaseName sysname
)
RETURNS sysname
--WITH SCHEMABINDING
--     Cannot schema bind table valued function 'dbo.GetCaseSensitiveCollation2'
--     because it references system object 'sys.fn_helpcollations'.
AS
BEGIN
  DECLARE @NewCollationName sysname;

  ;WITH collation(name) AS
  (
    SELECT CONVERT(sysname, COALESCE(@CollationName,
                DATABASEPROPERTYEX(COALESCE(@DatabaseName, DB_NAME()), 'Collation')))
  )
  SELECT @NewCollationName = col.[name]
  FROM   sys.fn_helpcollations() col
  CROSS JOIN collation
  WHERE  col.[name] = CASE WHEN collation.[name] LIKE N'%[_]CS[_]%'
                                THEN collation.[name]
                           ELSE REPLACE(collation.[name], N'_CI_', N'_CS_')
                      END;

  RETURN @NewCollationName;
END;
GO

例子:

/* Get CS Collation for the specified Collation */
SELECT dbo.GetCaseSensitiveCollation2(N'Indic_General_100_CI_AS_KS_WS', NULL)
                 AS [BySpecificCollation];
-- Indic_General_100_CS_AS_KS_WS

/* Get CS Collation based on database default for the specified database */
SELECT dbo.GetCaseSensitiveCollation2(NULL, N'msdb') AS [ByDefaultCollationForDB];
-- SQL_Latin1_General_CP1_CS_AS

/* Get CS Collation based on database default for the current database */
USE [ReportServer];
SELECT Test.dbo.GetCaseSensitiveCollation2(NULL, DB_NAME()) AS [CurrentDB];
-- Latin1_General_CS_AS_KS_WS

/* Get CS Collation based on database default for database where the function exists */
SELECT Test.dbo.GetCaseSensitiveCollation2(NULL, NULL) AS [DBthatFunctionExistsIn];
-- SQL_Latin1_General_CP1_CS_AS
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 SQL Server 中获取区分大小写的排序规则版本? 的相关文章

随机推荐

  • 如何在 C++ 中构建动态数组并将其返回给 C#/.NET

    我必须找到在 C Win32 端构建结构数组的方法 我没有初始数量的物品 调整该数组的大小应该非常快 构建列表后 我需要将其返回到 NET 因此 该数组 列表 应该转换为可以在 NET 端轻松读取的传输方式 或者可以 按原样 使用初始列表
  • 与枚举一起使用

    我有一个 JSP portlet 需要根据枚举类型的 bean 属性的值显示不同的标记 public enum State CANCELED COMPLETED 我使用以下代码来进行切换
  • mini_magick gem 不适用于我的 ImageMagick 安装

    我通过 MacPorts 和 mini magick gem 安装了 ImageMagick 并且收到以下脚本的错误 我该如何解决这个问题 require rubygems require mini magick image MiniMag
  • 如何在 Visual Studio 中显示交互式 Holoviews 图表(无需 Jupyter)?

    在使用 Holoviews 进行交互式绘图时 我主要使用 Jupyter Notebook Lab 如何让 Visual Studio 显示交互式图形和面板 而不使用 Visual Studio 中的交互式 Jupyter 在 Visual
  • NodeJS Web服务器“未定义不是一个函数”

    我刚刚浏览了一本书 pro Angularjs 中的教程 并且在设置 Nodejs Web 服务器时遇到了一些问题 就像书中描述的那样 我使用以下 server js 来创建它 var connect require connect con
  • R:将解释变量的动态数量拟合到多项式回归中

    假设给我一个数据框df在运行时 如何使用多项式回归拟合多项式模型 每个预测变量都是 df 中的一列 并且常数 k gt 2 的程度 困难在于 df 是在运行时读取的 因此在编写脚本时其列的数量和名称是未知的 但我确实知道响应变量是第一列 所
  • 解析类似 XML 的日志文件

    我有一个日志文件 记录事件如下 我想将每个事件转换为 PSCustomobject 它看起来有点像 XML 但将 xml 转换为文件的 Get Content 会出现错误 无法将值 System Object 转换为类型 System Xm
  • 如何检测 Botframework v4 中的对话结束?

    我试图在系统中的任何其他对话框完成后启动反馈对话框 我发现这个答案上面说要使用onEndDialog 但这不是 ActivityHandler 中的有效函数 只是onDialog 我的 主对话框 位于扩展 ActivityHandler 的
  • 在 MVC 3 应用程序中为模型中的对象属性创建视图?

    我有一个 Asp Net MVC 3 应用程序 其中包含一个由 EF 访问的数据库 Consultants 现在 数据库中的顾问表与其他几个表存在一对多关系 以获取简历类型信息 工作经验等 因此 用户应该能够填写一次他们的姓名等 但应该能够
  • pandas 中独立的多头列数据框

    请帮助将这个多帧熊猫分成单独的部分 这就是代码 import datetime as dt import pandas as pd import pandas datareader data as web pd set option dis
  • Android,以编程方式上传照片到 imgur 上托管

    我尝试了不同的方法来通过 imgur 上传和检索链接 但尽管查看了 imgur api 但没有一个成功 http api imgur com examples uploading java 但以下方法部分有效 我试图找回 错误 如果发生任何
  • Android 中连续的“Action_DOWN”

    Override public boolean onTouchEvent MotionEvent event if event getAction MotionEvent ACTION DOWN Log d VIEW LOG TAG Tou
  • Qt:使用二维数组值更新像素图网格布局

    我正在使用 Visual Studio 2010 和 Qt 4 7 都是 Windows 中的 C 组合进行游戏 该游戏是战舰的克隆 基于控制台输入 我已经按照我想要的样子创建了 gui 在 Qt 设计器的 Qt 端 我的 gui 由一个
  • 无法将 Entity Framework Core 迁移添加到 .NET Standard 2.0 项目

    我有一个包含许多项目的解决方案 其中之一 Domain 是一个 NET Standard 2 0 项目 我在其中创建了 EF CoreDbContext我想要启用的实现数据库迁移 我看到了各种博客和问答论坛 其中解释了问题 但由于 NET
  • 谷歌驱动器分页不起作用。清空 nextPageToken

    我正在 Symfony 中使用 Google Drive API 该库包含在以下行中composer json google apiclient 2 2 代码如下 service new Google Service Drive googl
  • 如何结合多处理和 eventlet

    我有一个任务需要启动 2 个进程 并且每个进程内需要启动 2 个线程才能真正工作 下面是我用来模拟我的用例的源代码 import multiprocessing import eventlet def subworker num1 num2
  • GCC 和 MS 编译器的模板实例化详细信息

    任何人都可以提供模板实例化方式的比较或具体细节吗 在 GCC 和 MS 编译器中的编译和 或链接时处理 这个过程有什么不同吗 在静态库 共享库和可执行文件的上下文中 我发现this doc关于 GCC 如何处理它 但我不确定这些信息是否 仍
  • “异步任务然后等待任务”与“任务然后返回任务”[重复]

    这个问题在这里已经有答案了 为了对异步编程和await 我想知道这两个代码片段在多线程以及执行顺序和时间上有什么区别 This public Task CloseApp return Task Run gt save database tu
  • 在silverlight中从字符串转换为数据?

    基本上我正在尝试这样做 Path path new Path string sData M 250 40 L200 20 L200 60 Z var converter TypeDescriptor GetConverter typeof
  • 如何在 SQL Server 中获取区分大小写的排序规则版本?

    有没有办法获得区分大小写的排序规则版本以在查询中使用 假设该查询可用于具有不同排序规则的数据库 其中一些排序规则不区分大小写 并且可以具有不同的区域性 例如多个客户端 但是 此查询应始终以区分大小写的方式运行 同时 如果可能 不更改排序规则