zoukankan      html  css  js  c++  java
  • SQL Server数据库查询区分大小写、全半角——排序规则的应用

    因为偶然的原因,需要在INNER JOIN联表时,让对应字段进行区分大小写的比较。而默认情况下建立的Sql Server数据库是不区分大小写的,这个需求怎么实现呢?

    要实现这个需求,至少有三个操作级别来实现:

    1. 数据库级别:整个数据库中的charvarchartextncharnvarcharntext 数据都区分大小写。(为描述方便,下文不再明确强调这些数据类型。)但这样做有个明显的坏处,那就是整个数据库的这些字段的比较,都要进行严格匹配。比如下面的两条Sql语句会得到完全不同的两种结果:

    SELECT * FROM [TABLE] WHERE [COLUMN] LIKE %KeyWord%SELECT * FROM [TABLE] WHERE [COLUMN] LIKE %keyword%

    因为数据库在比较时会严格按照大小写来区别,这样就会导致我们在程序开发过程中难以满足十分复杂的查询需求,特别突出的例子便是关键字搜索——我们无法预知客户输入内容的大小写,我们更不能要求客户输入的关键字区分大小写。

    image

    2. 表字段级别:只对特定的表字段进行大小写区分。这样做在整体上减小了大小写限定的范围,从全数据库减小到当前指定的字段。但使用起来仍然有些局限性。

    image

    3. 查询级别:只对本次查询限定大小写区分。这也是本文重点介绍的实现方式。这样操作可以让我们不对以前的数据库做任何的修改,只对当前这次查询区分大小写,也不会影响程序中别处对这些字段的查询。

    好了,上文说了三个实现级别,那具体怎么实现呢?这就要用到SQL数据库中的“排序规则”了。我们可以在数据库的属性上,设置排序规则,也可以在表设计的字段属性里设置排序规则。具体要设置什么样的排序规则,后面来说,我们先说查询级别的排序规则。下面有一段SQL片段可以演示在查询级别区分大小写的排序规则应用:

    use tempdb
    set nocount on
    --1--
    print '建立初始数据表Customer'
    create table Customer(id int,uname varchar(10))
    insert into Customer 
    select 1,'Jim' union all
    select 2,'Simith'  union all
    select 3,'uonun'
    
    select * from Customer
    
    --2--
    print '建立初始数据表Info'
    create table Info(uname varchar(10),phone varchar(11))
    insert into Info 
    select 'JIM','13800000000' union all
    select 'Simith','13911111111' union all
    select 'uonun','13812345678'
    
    select * from Info
    
    --3--
    print '不区分大小写,不区分全半角'
    select c.id,c.uname as 'c.uname',i.uname as 'i.uname',i.phone
    from Customer as c inner join Info as i
    on c.uname = i.uname
    
    --4--
    print '区分大小写,不区分全半角'
    select c.id,c.uname as 'c.uname',i.uname as 'i.uname',i.phone
    from Customer as c inner join Info as i
    on c.uname = i.uname
    collate Chinese_PRC_CS_AS
    
    --5--
    print '不区分大小写,区分全半角'
    select c.id,c.uname as 'c.uname',i.uname as 'i.uname',i.phone
    from Customer as c inner join Info as i
    on c.uname = i.uname
    collate Chinese_PRC_CI_AI_WS
    
    --6--
    print '区分大小写,区分全半角'
    select c.id,c.uname as 'c.uname',i.uname as 'i.uname',i.phone
    from Customer as c inner join Info as i
    on c.uname = i.uname
    collate Chinese_PRC_CS_AI_WS
    
    DROP TABLE Customer
    DROP TABLE Info
    
    
    /*
    建立初始数据表Customer
    id          uname
    ----------- ----------
    1           Jim
    2           Simith
    3           uonun
    
    建立初始数据表Info
    uname      phone
    ---------- -----------
    JIM        13800000000
    Simith     13911111111
    uonun      13812345678
    
    不区分大小写,不区分全半角
    id          c.uname    i.uname    phone
    ----------- ---------- ---------- -----------
    1           Jim        JIM        13800000000
    2           Simith     Simith     13911111111
    3           uonun      uonun      13812345678
    
    区分大小写,不区分全半角
    id          c.uname    i.uname    phone
    ----------- ---------- ---------- -----------
    2           Simith     Simith     13911111111
    3           uonun      uonun      13812345678
    
    不区分大小写,区分全半角
    id          c.uname    i.uname    phone
    ----------- ---------- ---------- -----------
    1           Jim        JIM        13800000000
    3           uonun      uonun      13812345678
    
    区分大小写,区分全半角
    id          c.uname    i.uname    phone
    ----------- ---------- ---------- -----------
    3           uonun      uonun      13812345678
    */

    通过上面的SQL语句可以看出,我们在查询时使用COLLATE字句,指定排序规则可以影响查询结果。通过上面的图也可以看出,这个排序规则除可以区分大小写之外,还可以区分重音、假名、全半角。

    结束语:

    1. 本文没有更深入研究排序规则的其他应用,比如对Order by的影响。
    2. 本文没有更深入研究在查询时对多个不同字段的影响机制。
    3. 示例代码另见CorePlex代码库http://udnz.com/Code-409.htm 

    参考《SQL Server 2008 联机丛书》:

    使用排序规则:ms-help://MS.SQLCC.v10/MS.SQLSVR.v10.zh-CHS/s10de_1devconc/html/61cdbb6b-3ca1-4d73-938b-22e4f06f75ea.htm

    COLLATE:ms-help://MS.SQLCC.v10/MS.SQLSVR.v10.zh-CHS/s10de_6tsql/html/76763ac8-3e0d-4bbb-aa53-f5e7da021daa.htm

  • 相关阅读:
    每个程序员都应该了解的内存知识
    关于CPU Cache -- 程序猿需要知道的那些事
    【转载】十分钟搞清字符集和字符编码
    初学 Java Web 开发,请远离各种框架,从 Servlet 开发
    XML
    接口比对象更加抽象
    【转载】Dom4j的使用(全而好的文章)
    BZOJ4870:[SHOI2017]组合数问题(组合数学,矩阵乘法)
    BZOJ1089:[SCOI2003]严格n元树(DP,高精度)
    BZOJ1259:[CQOI2007]矩形rect(DFS)
  • 原文地址:https://www.cnblogs.com/uonun/p/1941773.html
Copyright © 2011-2022 走看看