这里写自定义目录标题
- 1. 列排序规则与数据库默认值不匹配
- 1.1 sqlserver中的字符编码、排序规则、nvarchar和varchar
- 1.1.1 字符集、字符集编码和排序规则
- 1.1.1.1 字符集
- 1.1.1.3 字符集编码
- 1.1.1.4 排序规则
- 1.1.2 sqlserver中字符集编码和排序规则
- 1.1.2.1 sqlserver设置排序规则有四个级别:
- 1.1.2.2 排序规则如何选择问题
1. 列排序规则与数据库默认值不匹配
排序规则控制字符串的排序和比较方式。排序通常不是问题,因为它不会导致排序冲突。它可能不会按您希望的方式排序,但不会导致错误。这里真正的问题是在比较数据时。可以通过几种不同的方式进行比较。这可以是where子句中的简单比较,也可以是连接条件中的比较。如果数据库中的列与数据库的默认排序规则不匹配,那么您就有了一个等待发生的问题。
向现有表中添加新列或创建具有字符串列的新表时,如果未指定排序规则,则将使用数据库的默认排序规则。如果然后编写与现有列(具有不同排序规则)联接的查询,则会出现排序规则冲突错误。
这里要明确的是,我并不是建议每个字符串列都应该有一个与数据库的默认排序规则相匹配的排序规则。相反,我是在建议,当情况不同时,应该有一个很好的理由。有许多成功的数据库,开发人员从未考虑过排序规则。在这种情况下,最好使每个字符串列的排序规则与数据库的默认排序规则匹配。
如何检测此问题:
--当前数据库的排序规则
SELECT CONVERT(VARCHAR(100), DATABASEPROPERTYEX(DB_NAME(), 'Collation'))
--排序规则不同
SELECT C.TABLE_SCHEMA+'.'+C.TABLE_NAME+'.'+C.COLUMN_NAME [完全限定名(架构.表名.列名) ], C.COLLATION_NAME 列排序规则, DATABASEPROPERTYEX(DB_NAME(), 'Collation') 数据库排序规则
FROM INFORMATION_SCHEMA.COLUMNS C
INNER JOIN INFORMATION_SCHEMA.TABLES T ON C.TABLE_NAME=T.TABLE_NAME
WHERE T.TABLE_TYPE='BASE TABLE' AND COLLATION_NAME<>CONVERT(VARCHAR(100), DATABASEPROPERTYEX(DB_NAME(), 'Collation'))AND COLUMNPROPERTY(OBJECT_ID(C.TABLE_NAME), COLUMN_NAME, 'IsComputed')=0
ORDER BY C.TABLE_SCHEMA, C.TABLE_NAME, C.COLUMN_NAME;
如何更正: 要更正此问题,您可以修改现有字符串列的排序规则。
严重程度: 高
难度级别: 简单
1.1 sqlserver中的字符编码、排序规则、nvarchar和varchar
建议先阅读《细说ASCII、GB2312/GBK/GB18030、Unicode、UTF-8/UTF-16/UTF-32编码》
先说下结论:
- 如果你想在数据库中存储emoji表情等特殊字符,就需要将varchar改为nvarchar并且在编写sql语句时使用大N(N’小明…')。
- 默认的sqlserver中字符串的排序比较已忽略掉了全角/半角、大/小写的差别,所以不用担心因为大小写和全半角搜索不到数据的问题。
1.1.1 字符集、字符集编码和排序规则
1.1.1.1 字符集
罗列所有图形字符的一张大表。
比如:
- GBK字符集(中国制造): 罗列了所有的中文简体、繁体字的一张大表。
- Unicode字符集(全世界通用):罗列了世界上所有图形字符的一张大表。
1.1.1.3 字符集编码
将字符集上罗列的图形字符存储到计算机中的一种编码规则。
比如:
- GBK字符编码(中国制造):GBK本身既是字符集,也是编码规则;
- UTF-16:存储Unicode字符集的一种编码规则,使用2个(中文)、4个(emoji表情)字节存储。
- UTF-8:也是存储Unicode字符集的一种编码规则,使用1个、2个、3个、4个字节存储。
1.1.1.4 排序规则
定义各个图形字符之间的大小比较规则,比如:是否区分大小写,区分全角和半角等。
在软件使用中,一般我们只指定字符编码即可,因为确定了字符编码字符集自然就确定了。
但是在数据库类软件中,我们除了要指定编码规则,还需要指定排序规则,因为,数据库是要提供模糊匹配、排序显示功能的。
1.1.2 sqlserver中字符集编码和排序规则
上面虽然把字符集、字符集编码、排序规则的概念分的很清,但sqlserver中的配置并没有分的太清。
在sqlserver中没有单独设置字符集编码的地方,仅能设置排序规则。
至于最终使用什么字符集编码,则会受排序规则、数据类型(varchar、nvarchar)的影响。
一般我们在window或window server上安装sqlserver 2014,安装后默认排序规则是:Chinese_PRC_CI_AS。
Chinese_PRC:针对大陆简体字UNICODE的排序规则。
CI:CaseSensitivity,指定不区分大小写。
AS:AccentSensitivity,指定区分重音。
1.1.2.1 sqlserver设置排序规则有四个级别:
- 服务器级
- 数据库级
- 列级别文本
- 表达式级
注意:
Chinese_PRC_CI_AS不是存储为UTF8,事实上,直到SqlServer2019才引入UTF-8的支持(Chinese_PRC_CI_AS_UTF8)。
1.1.2.2 排序规则如何选择问题
通常我们在安装SQL Server 数据库时一般不会特意指定Server级的排序规则,那么SQL Server 在安装的时候是根据系统区域设置自动生成的的默认排序规则。举例:在Windows server 系统区域设置为安装数据库,因为向后兼容性的原因,默认安装的排序规则为:Chinese_PRC_CI_AS。
但是还是强烈建议安装数据库时将数据库的排序规则改为:Chinese_PRC_CS_AS。