UDF 中的 COLLATE 未按预期工作

2023-11-21

我有一个带有文本字段的表格。我想选择文本全部大写的行。该代码按其应有的方式工作,并返回ABC:

SELECT txt
FROM (SELECT 'ABC' AS txt UNION SELECT 'cdf') t
WHERE 
txt COLLATE SQL_Latin1_General_CP1_CS_AS = UPPER(txt)

然后我创建 UDF(按照建议here):

CREATE FUNCTION [dbo].[fnsConvert]
(
      @p NVARCHAR(2000) ,
      @c NVARCHAR(2000)
)
RETURNS NVARCHAR(2000)
AS
    BEGIN
        IF ( @c = 'SQL_Latin1_General_CP1_CS_AS' )
            SET @p = @p COLLATE SQL_Latin1_General_CP1_CS_AS
        RETURN @p    
    END

并按如下方式运行它(对我来说这看起来是等效的代码):

SELECT txt
FROM (SELECT 'ABC' AS txt UNION SELECT 'cdf') t
WHERE 
dbo.fnsConvert(txt, 'SQL_Latin1_General_CP1_CS_AS') = UPPER(txt)

但是,这会返回ABCcdf.

为什么会这样,我该如何让它发挥作用?

PS 我在这里需要 UDF 才能从 .Net LINQ2SQL 提供程序调用区分大小写的比较。


变量不能有自己的排序规则。它将始终使用服务器的默认值。检查一下:

--我声明了三个变量,每个变量都有自己的排序规则 - 至少有人可能这么认为:

DECLARE @deflt VARCHAR(100) = 'aBc'; --Latin1_General_CI_AS in my system
DECLARE @Arab VARCHAR(100) = 'aBc' COLLATE Arabic_100_CS_AS_WS_SC;
DECLARE @Rom VARCHAR(100) = 'aBc' COLLATE Romanian_CI_AI

——现在检查一下。所有三个变量都被视为系统的默认排序规则:

SELECT [name], system_type_name, collation_name
FROM sys.dm_exec_describe_first_result_set(N'SELECT @deflt AS Deflt, @Arab AS Arab, @Rom AS Rom'
                                          ,N'@deflt varchar(100), @Arab varchar(100),@Rom varchar(100)'
                                          ,0);

/*
name    system_type_name    collation_name
Deflt   varchar(100)        Latin1_General_CI_AS
Arab    varchar(100)        Latin1_General_CI_AS
Rom     varchar(100)        Latin1_General_CI_AS
*/

--现在我们检查“aBc”与“ABC”的简单比较

SELECT CASE WHEN @deflt = 'ABC' THEN 'CI' ELSE 'CS' END AS CheckDefault
      ,CASE WHEN @Arab = 'ABC' THEN 'CI' ELSE 'CS' END AS CheckArab
      ,CASE WHEN @Rom = 'ABC' THEN 'CI' ELSE 'CS' END AS CheckRom

/*CI    CI  CI*/

--但是我们可以为一个给定的操作指定排序规则!

SELECT CASE WHEN @deflt = 'ABC' THEN 'CI' ELSE 'CS' END AS CheckDefault
      ,CASE WHEN @Arab = 'ABC' COLLATE Arabic_100_CS_AS_WS_SC THEN 'CI' ELSE 'CS' END AS CheckArab
      ,CASE WHEN @Rom = 'ABC' COLLATE Romanian_CI_AI THEN 'CI' ELSE 'CS' END AS CheckRom

/*CI    CS  CI*/

--但是表的列会有不同的行为:

CREATE TABLE #tempTable(deflt VARCHAR(100)
                       ,Arab VARCHAR(100) COLLATE Arabic_100_CS_AS_WS_SC
                       ,Rom VARCHAR(100) COLLATE Romanian_CI_AI);

INSERT INTO #tempTable(deflt,Arab,Rom) VALUES('aBc','aBc','aBc');

SELECT [name], system_type_name, collation_name
FROM sys.dm_exec_describe_first_result_set(N'SELECT * FROM #tempTable',NULL,0);
DROP TABLE #tempTable;

/*
name    system_type_name    collation_name
deflt   varchar(100)        Latin1_General_CI_AS
Arab    varchar(100)        Arabic_100_CS_AS_WS_SC
Rom     varchar(100)        Romanian_CI_AI
*/

--这也适用于声明表变量。比较“知道”指定的排序规则:

DECLARE @TableVariable TABLE(deflt VARCHAR(100)
                            ,Arab VARCHAR(100) COLLATE Arabic_100_CS_AS_WS_SC
                            ,Rom VARCHAR(100) COLLATE Romanian_CI_AI);

INSERT INTO @TableVariable(deflt,Arab,Rom) VALUES('aBc','aBc','aBc');

SELECT CASE WHEN tv.deflt = 'ABC' THEN 'CI' ELSE 'CS' END AS CheckDefault
      ,CASE WHEN tv.Arab = 'ABC' THEN 'CI' ELSE 'CS' END AS CheckArab
      ,CASE WHEN tv.Rom = 'ABC' THEN 'CI' ELSE 'CS' END AS CheckRom
FROM @TableVariable AS tv

/*CI    CS  CI*/

更新一些文档

在这个链接您可以阅读有关详细信息。整理不改变值. It 应用规则(相关NOT NULL它不会更改值,而只是添加规则是否NULL可以设置也可以不设置)。

文档说得很清楚

是一个子句,可应用于数据库定义或列定义以定义排序规则,或应用于字符串表达式以应用排序规则转换。

稍后你会发现

  1. 创建或更改数据库
  2. 创建或更改表列
  3. 转换表达式的排序规则

更新2:解决方案的建议

如果您想控制比较是进行 CS 还是 CI,您可以尝试以下操作:

DECLARE @tbl TABLE(SomeValueInDefaultCollation VARCHAR(100));
INSERT INTO  @tbl VALUES ('ABC'),('aBc');

DECLARE @CompareCaseSensitive BIT = 0;
DECLARE @SearchFor VARCHAR(100) = 'aBc';

SELECT *
FROM @tbl 
WHERE (@CompareCaseSensitive=1 AND SomeValueInDefaultCollation=@SearchFor COLLATE Latin1_General_CS_AS)
   OR (ISNULL(@CompareCaseSensitive,0)=0 AND SomeValueInDefaultCollation=@SearchFor COLLATE Latin1_General_CI_AS);

With @CompareCaseSensitive set to 1它只会返回aBc, with NULL or 0它将返回两行。

这是——肯定的! - 性能比 UDF 好得多。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

UDF 中的 COLLATE 未按预期工作 的相关文章

随机推荐

  • 为什么我的断点在 Visual Studio 中重复?

    我最近开始在 Visual Studio 2010 中遇到断点问题 当我设置断点然后开始调试时 另一个断点出现在附近的其他行上 下面的屏幕截图显示了设置断点后的编辑器以及断点窗口 一旦我开始调试 断点就会重复 如以下屏幕截图所示 为什么会发
  • CodeIgniter 站点在子目录中,htaccess 文件可能会干扰主目录中的 htaccess 文件?

    在我的 CodeIgniter 网站 托管在 GoDaddy 上 中 导航到任何页面但索引都会出现此错误 未指定输入文件 谷歌搜索了一下 似乎原因一定与我的 htaccess 情况有关 设置的方式 也许最终会改变 是我的 CI 站点位于主域
  • NuGet 包未将 XMLDoc 文件与 dll 一起复制到 bin

    我正在使用 NuGet GUI 并尝试将 XML 文件与我的 DLL 一起包含以将帮助与 DLL 一起分发 当我在任何项目中安装包时 它都会成功添加 DLL 引用 但在添加包的项目的 bin 文件夹内未生成 XML 文件 XML 文件在pa
  • 如何计算 Ruby 数组中的重复元素

    我有一个排序数组 FATAL
  • Visual Studio 2005.RC 文件包括

    我正在 Visual Studio 2005 上使用 C 进行编程 我的问题涉及 rc 文件 您可以手动将包含指令 如 include blah h 放置在 rc 文件的顶部 但这是个坏消息 因为第一次有人在资源编辑器中打开 rc 文件时
  • 什么是 Android MultiDex?

    有很多关于 MultiDex 的帖子 我有时经历过解决错误 包括multiDexEnabled true in the defaultConfig我的 build gradle 部分 但是 这个功能到底是什么 使用场景有哪些 Quoting
  • Git 追踪上游

    我正在开发一个项目 并且有一个中央 git 存储库 该项目是一个框架 是许多分叉的基线 是否可以为分叉配置我的本地工作存储库 以跟踪项目的中心作为原点 并将骨架的主控作为名为上游的单独分支跟踪 跟踪骨架的主控以挑选对骨架的更改 我想我希望我
  • JavaScript“this”关键字和箭头函数

    Here this箭头函数中的关键字指向obj的可变环境 var greeting hi const obj greeting hey fo const greeting hola const arrowFo gt console log
  • 如何在数据框中添加一列来说明每行来自哪个工作表名称? Python

    我正在使用一个有五张纸的数据框 我想使用其中的四张 所以我可以将其加载到 df pd read excel xls sheet name a b c d 但现在我想添加一列来说明每行所在的工作表 但我不知道如何执行此操作 我尝试过这样的事情
  • Google-api-php 刷新令牌返回 invalid_grant

    我几乎搜索了谷歌第一页的所有结果 但似乎找不到答案 我正在使用 Google API 的刷新令牌并接收 Error refreshing the OAuth2 token message error invalid grant 我在做什么
  • 日期格式转换javascript

    我正在尝试使用 javascript 将 2013 年 7 月 24 日 转换为 DD MM YYYY 但我不断收到错误消息 我在用new Date July 24 2013 format DD MM YYYY 我缺少什么 Date对象没有
  • Python3.4 错误 - 无法启用可执行堆栈,因为共享对象需要:无效参数

    我一直在尝试安装OpenCV在 Windows 上的 Bash Linux 的 Windows 子系统 wsl 环境中 事实证明这非常困难 我想我已经非常接近了 但是进入 python 后 import cv2给出以下错误 ImportEr
  • 在文档 (.docx) 的特定位置添加图像?

    我使用 Python docx 生成 Microsoft Word 文档 用户希望当他写下这样的内容时 大家早上好 这是我的 profile img s 你喜欢吗 在 HTML 字段中 我创建一个 Word 文档 并从数据库中恢复用户的图片
  • 按值对数组进行排序并存储在变量中

    array array 5 4 6 8 5 3 4 6 1 我想排序 array like asort确实如此 但问题是asort是一个函数 它的乘积不能存储在变量中 我怎样才能做这样的事情 array array 5 4 6 8 5 3
  • 如何在 TextView 中的每个单词上使用 onTouchListeners?

    我想将 onTouchListeners 分配给 TextView 中的每个单词 不是链接到互联网上的某些内容 而是为了继续应用程序内的游戏逻辑 此时我的游戏的一般操作是查看 TextView 触摸一个单词 如果它是您获胜的目标单词 否则根
  • 如何从类函数内部访问对象属性[重复]

    这个问题在这里已经有答案了 我的 Javascript 类之一有时需要用 Json 更新 我一直在做一个函数 在给定一个 id 的情况下更新数据数组 但现在我想把它做得更封装 函数更新 在类内部 我做了什么 function File da
  • Angular 2 使用 FormBuilder 访问嵌套 FormArray

    首先 我刚刚从 Angular 2 开始 我正在尝试构建一个嵌套表单并验证它 这是我的 ts 文件的一部分 ngOnInit this myForm this formBuilder group projects this formBuil
  • JavaScript 的正则表达式表示法有什么问题?

    我正在读道格拉斯 克罗克福德的网页 JavaScript 世界上最容易被误解的编程语言 我不禁注意到 在 设计错误 下 他提到了 文字正则表达式的符号 他到底在说什么 JavaScript 的正则表达式表示法有什么问题 为什么 可能与它迫使
  • 将取消引用的智能指针的地址传递给需要原始指针的函数

    假设我正在使用需要使用原始指针的库或框架 使用拥有一些数据的智能指针 然后将取消引用的智能指针的地址传递给需要原始指针的函数 这是有效的做法吗 是的 这是有效的做法 这std智能指针有一个get 成员函数正是为了这个目的 一般来说 当您通过
  • UDF 中的 COLLATE 未按预期工作

    我有一个带有文本字段的表格 我想选择文本全部大写的行 该代码按其应有的方式工作 并返回ABC SELECT txt FROM SELECT ABC AS txt UNION SELECT cdf t WHERE txt COLLATE SQ