如何在 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 中获取区分大小写的排序规则版本? 的相关文章

  • SQL:从多个表中获取 USER 表中用户记录的计数。最好的方法是什么?

    我有4个SQL Server 2008版本 表 1 USER to store user information Fields UserId UserName 2 FILES to store files uploaded by user
  • 复制具有不同列名的 MySQL 表

    我需要将 table1 中与特定列匹配的所有行复制到具有不同列名称的 table2 中 例如 table1 name oldAddressBook table1 的列 name Name Surname Number table2 name
  • SQL Server 中带条件的多个计数函数

    我想合并 SQL Server 中的一些表 我想要获得的是如下图所示的东西 假设我有 tes A tes B tes C 和 tes jumlah 表 tes jumlah 是 tes A tes B 和 tes C 表的组合 请注意 ju
  • 从关键字后的文本中提取字符串

    我想从 SQL 字段中关键字后面的文本中提取内容 我有一个名为Description在表中 该字段的内容是 asdasf 关键字 狗 aeee 关键字 猫 ffffaa 关键词 狼 我想提取并保存 关键字 之后的文本 在本例中dog cat
  • SQL准备语句如何通过多个可能的菜单选择进行选择?

    所以我有 4 个菜单选择 产品 位置 课程类型和类别 所有这些都可以为空 使用 JSF 编程 但这应该与这个问题无关 因为它是一个 SQL 问题 菜单选择将向托管 bean 发送用户选择的变量 并使用准备好的语句使用用户选择的菜单中的信息
  • 如何在oracle sql查询中提取括号之间的字符串

    我正在尝试从字符串中提取括号之间的值 我怎样才能做到这一点 例如 我有这个字符串 Gupta Abha 01792 我想得到括号之间的结果 即 01792 我正在尝试编写这样的查询 select substr Gupta Abha 0179
  • 将 .sql 文件导入 SQLite

    我正在尝试将大型 sql 文件导入 SQLite db 文件 但出现以下错误 sqlite gt read smsCorpus en 2012 04 30 sql Error near line 23 near COMMENT syntax
  • 在表中添加新列,其值取决于同一表中另一列的值

    我是 Mysql 的新手 我想在表中添加一列 其值取决于同一个表中的另一个列值 例如我有company table如下 fldId companyName date 1 adeco 2012 01 12 2 mic 2001 03 09 3
  • Yii 添加条件

    我尝试根据我的条件从表中获取行 我的代码 conditions array id gt array 148028 118508 criteria new CDbCriteria foreach conditions as key gt va
  • 将多个子查询作为值插入

    假设我要插入一个有很多 fk 的表 只是为了在下面解释一下错误的说法 insert into mytable values somevalue somevalue select id from othertable1 where condi
  • 我们可以在 Azure 上的 T-SQL 过程中创建数据库范围的凭据吗

    我们可以在 Azure SQL 上的 T SQL 过程中为共享访问签名创建数据库范围的凭据吗 我们正在尝试从存储在 Azure blob 上的 csv 文件批量插入数据 以下是步骤 使用 JAVA 创建 SAS 凭证 Java将调用存储过程
  • 使用变量获取 SQL xml 属性值

    我有一个 SQL 函数 它接受一个名为attribute 这是我想要从中获取值的 xml 属性 xmlPath是完整的 XML 字符串 我的 xml 看起来像这样
  • 计算日期范围内的天数以及可能重叠的排除集

    给定以下示例查询 考虑到这些范围可能具有重叠的日期 并且还给出了一组要排除的范围 那么计算日期范围内的总天数的合理且高效的方法是什么 更简单地说 我有一个表 其中包含一组关闭计费的日期范围 我从一个日期范围 例如 Jan1 Jan31 开始
  • 将具有重复值的数据插入 Postgresql

    我需要在 postgresql 中插入数据集 INSERT INTO table subject topics exams name of subject section topic subtopic VALUES Algebra Math
  • 将 XML 文件读取到已存在的数据库表中

    我正在尝试将 XML 文件读入已存在的数据库表中 问题是 XML 标签和数据库列的名称不同 尽管它们具有相同的数据类型 因此 我想将 XML 标签 翻译 到数据库列中 以便可以输入数据库 不过我不知道该怎么做 这是我到目前为止所做的 sta
  • 条件聚合性能

    让我们有以下数据 IF OBJECT ID dbo LogTable U IS NOT NULL DROP TABLE dbo LogTable SELECT TOP 100000 DATEADD day ABS CHECKSUM NEWI
  • sql自连接表删除重复行

    我有下表 USERID LANGUAGEID 1 2 1 7 1 8 2 10 2 3 现在我想为每个用户创建所有可能的语言对 这意味着我希望结果集是 对于用户 1 2 7 7 8 2 8 对于用户 2 10 3 为此 我做了以下查询 SE
  • 如何为基于服务的数据库设置自动增量

    我在这里开始构建我的第一个本地数据库 基于服务的数据库 使用文本框将行写入基于服务的数据库 https stackoverflow com questions 39152801 write line to service based dat
  • 更改 MySQL 中的列名称 [重复]

    这个问题在这里已经有答案了 搜索后我不知道我需要在 ALTER TABLE 中做什么genres更改列id to genre id有任何想法吗 alter table genres change id genre id int 10 aut
  • SQL 中 NOT 和 != 运算符有什么区别?

    有什么区别NOT and SQL 中的运算符 我无法理解其中的区别 我猜他们是一样的 NOT negates以下条件 因此它可以与各种运算符一起使用 is the 非标准替代品 https stackoverflow com a 10650

随机推荐

  • 如何在 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 中获取区分大小写的排序规则版本?

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