有时候,一个简单的字符比较,你可能也会被弄得晕头转向。为什么这样说呢?请看下面这个例子(代码就不贴了,因为后来发现页面不支持这两个字符的显示)。猜测一下,会是什么结果?是1还是0? 回答这个问题之前,请再继续向下看。先创建几个不同排序规则的数据库(见数据库名可知)。

Figure-1: 在SQL_Latin1_General_CP1_CI_AS排序规则下的比较

Figure-2: 在Chinese_PRC_CI_AS排序规则下的比较

在SQL_Latin1_General_CP1_CI_AS或是Chinese_PRC_CI_AS两不同的排序规则下,这两个字符竟然是相等的!!很明显看起来就是不相等嘛!使用了UNICODE函数转换也无效。怎么回事呢?!下面就是这个问题的解答。原文是英文,我已经翻译成中文(英语水平有限,错漏难免,最好还是看原文哈)。

附上原文地址:

http://blogs.msdn.com/b/sqlprogrammability/archive/2006/04/07/570397.aspx

未定义的字符在Unicode或Windows排序规则中的排序问题

当在非二进制排序规则中比较两个Unicode字符串时,SQL Server使用一个跟Windows API CompareStringW基本相同的库。这个库为每个已经辨识的字符定义了一个权重值(Weight),并以这个权重值进行字符的比较。然而,并不是所有代码点(code point)都已经在排序库中进行了定义。它们可能被未定义的原因是:

  1. 代码点在Unicode标准中未进行定义。

  2. 代码点在Unicode标准中已进行了定义,但在Windows中却未进行定义。这需要花费时间和精力为新的字符定义语言语义的排序。Windows团队通常需要与当时标准组织和/或地区项目经理合作,为新的字符定义排序规则。他们在每个版本中添加新字符的支持,并试图迎头赶上。有些字符也许已经具有字体的定义,因此可能会正常地显示,但仍然没有对比较进行定义。比如NCHAR(13144) - NCHAR(13174)。

  3. 代码点在Windows进行了定义,但未在SQL Server中定义。

Windows NLS团队已经决定,未定义的字符进行比较时将被忽略,部分原因是没有一个好的办法将未定义的字符和其他已经定义的字符进行比较。SQL Server继承了这一语义。这确实导致了一些令人感觉困惑的行为。看看下面的例子。

declare @undefined_char1 nvarchar(10), @undefined_char2 nvarchar(10)
set @undefined_char1 = nchar(0x0000)
set @undefined_char2 = nchar(13144)
select 'Undefine characters compare equal to empty string'
where @undefined_char1 = ''
select 'All undefine characters compare equal'
where @undefined_char1 = @undefined_char2
go
create table t (c nvarchar(10))
go
create unique index it on t(c)
go
-- first insert succeeds, but second insert fails with duplicate key error.
insert t values (nchar(0x0000))
insert t values (nchar(13144))
go

正如你所见,由于所有未定义的字符比较都为相等的,他们会导致重复键的错误。同理,如果你创建一张未定义字符为表名的表,然后尝试创建另一个未定义字符为表名的表,第二张表会因为表名重复而创建失败,即使这两个未定义字符的代码点是不同的。这也可能导致混淆的结果出现在如CHARINDEX, PATINDEX或LIKE等内置的字符串匹配(功能)中。

虽然这些结果似乎令人迷惑不解,但基本规则其实很简单。即未定义字符和字符串的比较将被忽略。一旦你明白并记住这个规则,这个行为就很容易理解了。

只要有未定义字符的参数将被忽略。由于这是在Windows平台上的行为,没有一个绝对的更好的方法对它们进行排序,并且向后兼容,我们要保持这种行为。

如果你的应用程序要使用到这些未定义的字符,并且把它们当成常规字符处理,你可以使用二进制的排序规则(binary collation)。在二进制排序规则中,比较完全是根据代码点,不是语言规则,因此也没有所谓的已定义和未定义的概念了。(完)

读完这篇博客,你应该明白怎么回事了吧。原因就是:跟未进行定义的字符作比较时,SQL Server视为相等的。如果实际应用中要视为常规字符,转为二进制比较即可。因为二进制的比较就单纯的按照字符的代码点比较了。所以解决最开始的问题不难,如下:

Figure-3: 转为Latin1_General_BIN排序规则下的比较

不难推导出,在二进制排序规则下的数据库中,默认下,这两个字符是不相等的。

Figure-4: 在Latin1_General_BIN排序规则下的比较

Figure-5: 在SQL_Latin1_General_CP1_CI_AS排序规则下无法插入两行记录

Figure-6: 在Latin1_General_BIN排序规则下,成功插入这两行记录。

转载于:https://blog.51cto.com/fishparadise/1751562

你可能不知道的字符比较中的“秘密”相关推荐

  1. Python可以做什么?你所不知道的Python——生活中的奇妙用途

    大家都知道Python可以用来做数据分析.爬虫,甚至是人工智能,但却觉得那些东西比较遥远,会担心孩子学Python为时过早. Python 其实Python并不只是能做一些很专业.高端的应用,它在生活 ...

  2. DNS解析过程中不得不知道的那些事

    DNS解析过程中不得不知道的那些事 0x01 定义 0x02 域名结构 0x03 DNS查询方式 1.从查询方式分类 2.从查询内容: 0x04 常见的DNS资源记录 1.A/AAAA记录 2.CNA ...

  3. 「从源码中学习」面试官都不知道的Vue题目答案

    前言 当回答面试官问及的Vue问题,我们除了照本宣科的回答外,其实还可以根据少量的源码来秀一把,来体现出你对Vue的深度了解. 本文会陆续更新,此次涉及以下问题: "new Vue()做了什 ...

  4. 国际计算机思维比赛,少儿编程领域中,你所不知道的国际计算思维大赛

    原标题:少儿编程领域中,你所不知道的国际计算思维大赛 孩子学习编程,除了培养编程思维和计算思维,也能为未来应对人工智能时代打下基础.今天给大家讲的的是Bebras国际计算思维大赛,请大家持续关注坚果学 ...

  5. axure中出现小手_你所不知道的15个Axure使用技巧

    Axure 6.5已于4月18日发布,可直到上周我才发现,于是赶紧下载升级.等待下载的过程中,闲来无聊跑去看了Axure的版本历史,又浏览了一下官方的使用教程,忽然发现Axure竟如此博大精深,自己平 ...

  6. php h5支付没有返回app中,很多人都不知道的监听微信、支付宝等移动app及浏览器的返回、后退、上一页按钮的事件方法...

    在实际的应用中,我们常常需要实现在移动app和浏览器中点击返回.后退.上一页等按钮实现自己的关闭页面.调整到指定页面或执行一些其它操作的 需求,那在代码中怎样监听当点击微信.支付宝.百度糯米.百度钱包 ...

  7. 在html页面中的js如何调试,你可能不知道的14个JavaScript调试技巧

    以更快的速度和更高的效率调试你的 JavaScript 了解你的工具可以在完成任务的过程中发挥重大作用.尽管传言 JavaScript 难以调试,但是如果你掌握了一些调试技巧,那么你将会花费更少的时间 ...

  8. 图片浏览器每次只能打开一张图片_那些你可能不知道的浏览器奇技淫巧

    搬运自我的公众号文章 那些你可能不知道的浏览器奇技淫巧 平常工作少不了用浏览器,以下分享一些浏览器的使用技巧,更好的有助于你的工作. ps: 以下技巧均在 Chrome 浏览器下测试的. 网页长截图 ...

  9. servlet后台如何接受multpartfile_Servlet进阶教程(你不得不知道的Servlet知识点)

    " 人生的游戏不在于拿了一副好牌,而在于怎样去打好坏牌,世上没有常胜将军,勇于超越自我者才能得到最后的奖杯." 你好,我是梦阳辰!快和我一起学习吧! 精彩回放: Servlet入门 ...

最新文章

  1. PTP4L命令手册(谷歌翻译)
  2. 【BZOJ-2669】局部极小值 状压DP + 容斥原理
  3. Git/TortoiseGit使用
  4. java数组子类型_[改善Java代码]数组的真实类型必须是泛型类型的子类型
  5. 使用机器学习预测电子竞技游戏《守望先锋》的胜负
  6. Javascript实现AES加密解密(ECB/CBC)
  7. 如何查看IIS的80端口被占用?
  8. python制作词作云动画_3分钟教你用python制作一个简单词云
  9. 世界首次发现?包名导致eclipse找不到包含main的类
  10. linux下exe软件反编译工具下载,ilspy.exe
  11. 基于Python的FreeCAD二次开发
  12. android CTS GTS 环境搭建
  13. pe和linux一起安装到移动硬盘,PE安装在移动硬盘的详细教程
  14. openCamera的 hal 端流程
  15. 汇编语言 查看存储器中的数据
  16. day4 vue 学习笔记 组件 生命周期 数据共享 数组常用方法
  17. 为什么在马云成功前就有那么多影像留下来?
  18. php图片生成邀请函,科学网—如何制作邀请函 - 樊晓英的博文
  19. MySQL索引原理理解
  20. Ormlite 介绍 一

热门文章

  1. 20220212:力扣第277场周赛(下)
  2. 20210701:随机信号的功率谱估计相关算法的实现
  3. oracle的表空间的检查,oracle数据库检查所有表空间使用率的脚本
  4. ArrayList<object> list 转org.json.JSONArray
  5. vmware下安装rhel5
  6. AI向程序员老司机学习:从眼神的变化中寻找bug
  7. 阿里官宣AI框架大牛贾扬清加盟,任职技术VP
  8. 华为云回答2018:AI差异化初见成效,已吹响进攻号角
  9. 苹果编程套餐更新,新增创意课程,十一拿起吃灰的iPad学起来!
  10. 马库斯:DeepMind新出的机器心智网络不错,但有误导性