• 注意Vietnamese_CI_AS排序规则下的特殊字符大小敏感问题


    注意Vietnamese_CI_AS排序规则下的特殊字符大小敏感问题

     

    最近,在SQL Server中遇到了Vietnamese_CI_AS排序规则的特殊字符的大小写敏感问题,是的,你没有看错,这句话并没有语病(DBA老司机懂的)。遇到这个特殊情况的时候,我也大跌眼镜,颠覆我的一些常识,OK,闲话少说,我们来演示一下这个特殊场景下出现的特殊情况。

     

    准备测试环境:

     

        服务器排序规则(Server Collation           Latin1_General_CI_AS

        数据库排序规则(Database Collation)      :   Vietnamese_CI_AS

     

    注意,只有在这个特定排序规则下才会出现这个问题,准备好了测试环境后,我们先简单聊几句关于排序规则的知识,SQL Server里面的排序规则其实是包含了字符集和排序规则两样东西,不像MySQL,字符集和排序规则概念和设置分开。如果你想查看某个排序规则对应的字符集,那么就可用下面的SQL语句查看。如下截图所示:

       

    SELECT  COLLATIONPROPERTY('Vietnamese_CI_AS', 'CodePage')                AS CodePage ,
            COLLATIONPROPERTY('Vietnamese_CI_AS', 'ComparisonStyle')        AS ComparisonStyle ,
            COLLATIONPROPERTY('Chinese_PRC_CI_AS', 'CodePage')                AS CodePage ,
            COLLATIONPROPERTY('Chinese_PRC_CI_AS', 'ComparisonStyle')        AS ComparisonStyle ,
            COLLATIONPROPERTY('SQL_Latin1_General_CP1_CI_AS', 'CodePage')    AS CodePage ,
            COLLATIONPROPERTY('SQL_Latin1_General_CP1_CI_AS', 'ComparisonStyle') AS ComparisonStyle

     

     

    clip_image001[4]

     

     

     

    Code Page

    Language

     

    932

    Japanese

    日语

    936

    Simplified Chinese

    简体中文

    949

    Korean

    韩文

    950

    Traditional Chinese

    繁体中文

    1258

    Vietnamese

    越南语

     

    从上可以看到Chinese_PRC_CI_AS的编码为936,如果对编码比较熟悉的就很清楚,但是可能也有一些对这个不太了解。下面简单述说一下,

     

     

     所谓代码页(code page)就是针对一种语言文字的字符编码。例如GBK的code page是CP936 ,BIG5的code page是CP950,GB2312的code page是CP20936。

     

     GBK是国家标准GB2312基础上扩容后兼容GB2312的标准。GBK的文字编码是用双字节来表示的,即不论中、英文字符均使用双字节来表示,为了区分中文,将其最高位都设定成1。GBK包含全部中文字符,是国家编码,通用性比UTF8差,不过UTF8占用的数据库比GBK大。

     

    UTF-8:Unicode TransformationFormat-8bit,允许含BOM,但通常不含BOM。是用以解决国际上字符的一种多字节编码,它对英文使用8位(即一个字节),中文使用24位(三个字节)来编码。UTF-8包含全世界所有国家需要用到的字符,是国际编码,通用性强。UTF-8版本虽然具有良好的国际兼容性,但中文需要比GBK/BIG5版本多占用50%的数据库存储空间。

     

    排序规则的后半部份即后缀 含义:

    _BIN            指定使用向后兼容的二进制排序顺序。

    _BIN2         指定使用 SQL Server 2005 中引入的码位比较语义的二进制排序顺序。

    _Stroke     按笔划排序

    _CI(CS)     是否区分大小写,CI不区分,CS区分(case-insensitive/case-sensitive)

    _AI(AS)     是否区分重音,AI不区分,AS区分(accent-insensitive/accent-sensitive)

    _KI(KS)     是否区分假名类型,KI不区分,KS区分(kanatype-insensitive/kanatype-sensitive)

    _WI(WS)     是否区分全半角, WI不区分,WS区分(width-insensitive/width-sensitive)

     

    好了,简单概述了一些关于编码和字符集的知识。那么我们来看看Vietnamese_CI_AS的Code Page为1258,这个是越南语言的一个字符集,很多人可能没有用过这个,不过没有关系。那么我们先来看看问题。准备测试环境和数据,如下所示

     

     

     

    USE  TEST;

    GO

     

    CREATE TABLE TEST (name NVARCHAR(12));

     

    INSERT INTO TEST

    SELECT N'lienht' UNION ALL

    SELECT N'LienHT' UNION ALL

    SELECT N'LienHt'

     

     

    SELECT * FROM TEST WHERE name ='lienHt';

    SELECT * FROM TEST WHERE name ='lienht'

    SELECT * FROM TEST WHERE name ='LIenht'

    SELECT * FROM TEST WHERE name ='LIeNht'

     

     

     

    clip_image002[4]

     

    clip_image003[4]

     

     

    如上测试截图所示,只有N、H或NH的组合会出现大小写敏感问题,其它字符没有这种情况,测试的时候,确实是颠覆我的三观,相当的惊讶和不解,然后我测试了不同排序规则,以及不同数据库版本,发现这个只在服务器排序规则为Latin1_General_CI_AS,数据库排序规则为Vietnamese_CI_AS,不管是SQL Server 2008、SQL Server 2012、 SQL Server 2014都会出现这个问题。网上搜索并没有很多资料,并没有什么答案,猜测跟Vietnamese的编码有关系,这个bug是同事在越南的项目遇到并发出来的。另外,在网上也发现有类似的求助 https://social.msdn.microsoft.com/forums/sqlserver/en-US/e634864a-13b5-49cd-a91d-0af38b5ce16c/tsql-like-1n 。遇到有这样场景的就需要格外小心了。解决方案,服务器排序规则和数据库排序规则一致肯定可以避免这个问题,另外临时解决方案就是在SQL语句中指定排序规则,如下所示:

     

     

     

    clip_image004[4]

  • 相关阅读:
    【MySQL】DBA必备的10款最佳MySQL GUI工具
    【MySQL】获取MySQL崩溃时的core file
    字符串经常用的
    centos 系统上如何把python升级为3
    centos6 升级安装openssh7
    多进程
    队列
    线程池,锁,事件
    thread
    进程、线程
  • 原文地址:https://www.cnblogs.com/kerrycode/p/7779151.html
Copyright © 2020-2023  润新知