环境:

  • sqlserver 2014
  • window 10

建议先阅读《细说ASCII、GB2312/GBK/GB18030、Unicode、UTF-8/UTF-16/UTF-32编码》

先说下结论:

  • 如果你想在数据库中存储emoji表情等特殊字符,就需要将varchar改为nvarchar并且在编写sql语句时使用大N(N'小明...')
  • 默认的sqlserver中字符串的排序比较已忽略掉了全角/半角、大/小写的差别,所以不用担心因为大小写和全半角搜索不到数据的问题。

一、说说字符集、字符集编码和排序规则

  • 字符集:罗列所有图形字符的一张大表。

    比如:

    • GBK字符集(中国制造): 罗列了所有的中文简体、繁体字的一张大表。
    • Unicode字符集(全世界通用):罗列了世界上所有图形字符的一张大表。
  • 字符集编码:将字符集上罗列的图形字符存储到计算机中的一种编码规则。

    比如:

    • GBK字符编码(中国制造):GBK本身既是字符集,也是编码规则;
    • UTF-16:存储Unicode字符集的一种编码规则,使用2个(中文)、4个(emoji表情)字节存储。
    • UTF-8:也是存储Unicode字符集的一种编码规则,使用1个、2个、3个、4个字节存储。
  • 排序规则:定义各个图形字符之间的大小比较规则,比如:是否区分大小写,区分全角和半角等。

在软件使用中,一般我们只指定字符编码即可,因为确定了字符编码字符集自然就确定了。

但是在数据库类软件中,我们除了要指定编码规则,还需要指定排序规则,因为,数据库是要提供模糊匹配、排序显示功能的。

二、sqlserver中字符集编码和排序规则

上面虽然把字符集、字符集编码、排序规则的概念分的很清,但sqlserver中的配置并没有分的太清。

在sqlserver中没有单独设置字符集编码的地方,仅能设置排序规则。

至于最终使用什么字符集编码,则会受排序规则、数据类型(varchar、nvarchar)的影响。

一般我们在window或window server上安装sqlserver 2014,安装后默认排序规则是:Chinese_PRC_CI_AS

Chinese_PRC:针对大陆简体字UNICODE的排序规则。
CI:CaseSensitivity,指定不区分大小写。
AS:AccentSensitivity,指定区分重音。

sqlserver设置排序规则有四个级别:

  • 服务器(示例级别):

  • 数据库:

  • 列级别:

  • 表达式级别:

    SELECT name FROM customer ORDER BY name COLLATE Latin1_General_CS_AI;
    

注意:
Chinese_PRC_CI_AS不是存储为UTF8,事实上,直到SqlServer2019才引入UTF-8的支持(Chinese_PRC_CI_AS_UTF8)。

参照:
《Introducing UTF-8 support for SQL Server》
《排序规则和 Unicode 支持》

附:查询排序规则元数据

-- 查询数据库的排序规则
select serverproperty(N'Collation');--查询所有受支持的排序规则
select * from fn_helpcollations()-- 查询列的排序规则
select name,collation_name from sys.columns where collation_name is not null

三、排序规则对sql语句的一影响

观察排序规则对sql语句影响的时候,我主要从以下两个方面考虑:

  • 全角/半角
  • 大写/小写

至于其他的重音、假名则是很难用到,直接用默认的即可。

分析其他数据库的排序规则时,也可以从这两个方面考虑,经过综合对比,sqlserver中的排序规则还是很贴近实际情况的,其他的数据库或多或少都有问题。

全角/半角对查询的影响:

我们期望的效果:当使用like查询或=比较符时,数据库能忽略掉全角“a”和 半角"a",将它们判定相等。
sqlserver不负众望,默认情况下的比较是忽略全角/半角的,所以,sqlserver能做到判定它们相等。

看如下实验:

create table test(id int identity(1,1),name varchar(50)
);
insert into test values
('角a啊'),--全角a
('角a啊');--半角a--测试like中的全角半角处理
select * from test where name like '%a%';--半角a
select * from test where name like '%a%';--全角a--测试=中的全角半角处理
select * from test where name = '角a啊';--半角a
select * from test where name = '角a啊';--全角a

上面的查询结果均显示:

大小写对查询的影响:

我们期望的效果:当使用like查询或=比较符时,数据库能忽略掉大写和小写的区别,将它们判定相等。
sqlserver不负众望,默认情况下的比较是忽略大小写的,所以,sqlserver能做到判定它们相等。

看如下实验:

create table test(id int identity(1,1),name varchar(50)
)insert into test values
('A'),('a');select * from test where name like 'A';
select * from test where name like 'a';select * from test where name = 'A';
select * from test where name = 'a';

上面的查询结果均显示:

四、sqlserver究竟会以何种编码存储字符

上面只说了sqlserver中的默认排序规则:Chinese_PRC_CI_AS,但是sqlserver中究竟是以哪种编码规则存储的呢?

具体用什么编码规则存储不仅受排序规则的影响,还受数据类型的影响(nvarchar、varchar)。

Chinese_PRC_CI_AS排序规则为例:

当我们使用varchar类型时,存储到表里面的数据其实就是GBK编码,因为:Chinese_PRC对应的是区域编码(ANSI,活动代码页:936)是GBK。可以通过sql查询得知:

SELECT COLLATIONPROPERTY('Chinese_PRC_CI_AS', 'CodePage')


当我们使用nvarchar类型时,存储到表里面的是UTF-16的编码。

验证不同数据类型对应的编码规则:

首先,我们数据库的排序规则是:Chinese_PRC_CI_AS,已知 汉字“王”的各种格式编码如下:

参考:《细说ASCII、GB2312/GBK/GB18030、Unicode、UTF-8/UTF-16/UTF-32编码》

准备数据:

create table test(name varchar(50),nname nvarchar(50)
)
insert into test values('王','王')select name,nname,convert (varbinary (20) , name) as name_binary,convert (varbinary (20) , nname) as nname_binary
from test


由此,可以看出,数据表中存储使用的字符编码和排序规则和数据类型都有关系。

具体可以参考:《nchar 和 nvarchar (Transact-SQL)》

五、sqlserver中数据类型varchar和nvarchar的区别、N’'的作用

其实从上面的实验中可以看得出来,对于Chinese_PRC_CI_AS排序规则来说:

  • varchar类型的列使用ANSI编码,也即GBK存储数据(不能存储emoji表情);
  • 而nvarchar类型的列使用UTF-16编码存储数据(能存储所有Unicode字符,包含emoji表情)。

我们知道,UTF-16编码规则最少使用2个字节存储字符,即使对于英文字母“W”也要使用两个字节,而GBK编码则可以使用1个字节存储英文字母“W”,所有当只有英文字母时,varchar显然要节省空间。

下面是存储英文字母“W”的示例:

create table test(name varchar(50),nname nvarchar(50)
)
insert into test values('W','W')select name,nname,convert (varbinary (20) , name) as name_binary,convert (varbinary (20) , nname) as nname_binary
from test

nvarchar(8000)和varchar(8000) 中的8000指的是字节数,而不是字符数,GBK中一个字符可以是1个字节或两个字节,UTF-16中一个字符则是2个或4个字节,所以在计算最多存储多少文字时不要搞错了。

N’小明’ 的作用:

这个大N表示单引号中的字符串使用的是Unicode编码,当我们sqlserver引擎会用Unicode的方式去解析"小明",而不是用GBK编码的方式。

一般来说,我们感觉不到加不加大N的区别,那是因为我们存储的数据都在Unicode的常见字符区域内,如果我们存储一个emoji表情,那么加不加大N的就立马看得出来了,看如下的实验:

create table test(name varchar(50),nname nvarchar(50)
)
insert into test values('王','王')
insert into test values(N'王',N'王')
insert into test values('W','W')
insert into test values(N'W',N'W')
insert into test values('												

sqlserver中的字符编码、排序规则、nvarchar和varchar、大N‘‘相关推荐

  1. sql server中字符集和排序规则到底什么关系

    --SQLSERVER 中的排序规则 服务器>数据库>表列 --------------------------------- 排序规则简介 ----------------------- ...

  2. mysql 中文字符排序规则_mysql中字符集和排序规则说明

    数据库需要适应各种语言和字符就需要支持不同的字符集(Character Set),每种字符集也有各自的排序规则(Collation). 一.字符集 字符集,即用于定义字符在数据库中的编码的集合. 常见 ...

  3. mysql concat 不同字符集_字符编码 - 如何将整个MySQL数据库字符集和排序规则转换为UTF-8?...

    字符编码 - 如何将整个MySQL数据库字符集和排序规则转换为UTF-8? 如何将整个MySQL数据库字符集转换为UTF-8并将整理转换为UTF-8? 17个解决方案 591 votes 使用utf8 ...

  4. mysql中一次字符集和排序规则引起的sql查询报错

    先看sql o.city_name AS '城市',o.city_code AS '城市编码',o.comp_name AS '公司',o.comp_code AS '分公司编码',b.brand_n ...

  5. mysql选择排序规则_关于mysql创建数据库中字符集和排序规则的选择

    1:字符集: 一般 主要选择两种: 1:utf8   (看unicode编码区从1 - 126就属于传统utf8区,),一般都够用,除非需要存储特殊字符 2:utf8mb4(utf8mb4兼容utf8 ...

  6. mysql默认字符集和排序_MySQL字符集和排序规则

    MySQL在创建数据库是,需要设置数据库的字符集和排序规则,如图所示: 我觉得这里有必要解释下字符集和排序规则这两个概念. 字符集 说到字符集,需要先提下字符.字符集和字符编码这几个词的含义. 字符( ...

  7. 谈谈Windows程序中的字符编码

    sourece:http://www.fmddlmyy.cn/text7.html 谈谈Windows程序中的字符编码 写这篇文章的起因是这么一个问题:我们在使用和安装Windows程序时,有时会看到 ...

  8. MySQL字符集和排序规则详解

    本篇博客主要记录mysql当中关于创建数据库时候选择:字符集.排序规则等相关知识.通过示例直观的看出其真正作用. 目录 1.前言 2.mysql字符集 2.排序规则 2.1.排序规则作用 2.2.排序 ...

  9. System.Text.Json 中的字符编码

    System.Text.Json 中的字符编码 Intro 默认的 System.Text.Json 序列化的时候会把所有的非 ASCII 的字符进行转义,这就会导致很多时候我们的一些非 ASCII ...

最新文章

  1. 编程能力差,学不好Python、AI、Java等技术,90%是输在了这点上!
  2. Spring Cloud Alibaba发布第二个版本,Spring 发来贺电
  3. python开发的优秀界面-八款常用的 Python GUI 开发框架推荐
  4. [Flex]Flex SDK 4(Gumbo)更方便的自定义样式、自定义SparkSkin(三)
  5. vue踩坑- 报错npm ERR! cb() never called!
  6. linux apache设置web访问重定向_从零开始学Linux运维|30.Linux的目录结构
  7. App.js实现使用js开发app的应用,此文是中文文档
  8. applecare多少钱?_否,AppleCare +无法覆盖丢失或被盗的iPhone
  9. 什么是社会性网络?什么是六度分隔理论?
  10. 【codevs3732】【BZOJ3751】解方程,hash+秦九韶算法
  11. OpenCV2:Mat介绍及常见用法
  12. python︱函数、for、if、_name_、迭代器、防范报错、类定义、装饰器、argparse模块、yield
  13. 【笔记】c c++如何打印变量地址
  14. 嵩天python_跟着北京理工大学嵩天老师学习Python
  15. 推贴B2B/B2C订货商城系统 V3.0版
  16. 高一下学期计算机,高一信息技术下学期教学计划
  17. 缺项级数的收敛域求解
  18. 【es6学习】Babel 转码器详解
  19. 域名邮箱什么,如何开通自定义邮箱后缀的邮箱?
  20. 十个前端程序员必备的网站

热门文章

  1. gm220s路由器怎么设置_迷你路由器怎么设置
  2. 日本KDDI与高速巴士公司共同推出包月打车服务
  3. touch bar的4个使用小技巧
  4. AI+智慧城市,建设繁荣宜居天津滨海新区
  5. win7html.exe,Win7无法打开exe可执行文件弹出打开方式的对话框
  6. mysql 如何设置延迟启动_技术分享 | MySQL 网络延时参数设置建议
  7. Runnable和Thread比较
  8. Java周总结_mysql_jdbc
  9. 写一个python程序,要求能够输入关键词,而后输入一段句子可以检查出句子中的与关键词类似的错别字,并标记出来...
  10. python 二重积分_python中求二维积分的方法