SQL Server 2019 (15.x) 完全支持广泛使用的 UTF-8 字符编码作为导入或导出编码,以及作为字符串数据的数据库级别或列级别排序规则。 UTF-8 受 char 和 varchar 数据类型支持,并在创建对象的排序规则或将其更改为带有 UTF8 后缀的排序规则时启用。 例如,将 LATIN1_GENERAL_100_CI_AS_SC 更改为 LATIN1_GENERAL_100_CI_AS_SC_UTF8 。

UTF-8 仅适用于支持增补字符的 Windows 排序规则,如 SQL Server 2012 (11.x) 中所述。 nchar 和 nvarchar 数据类型仅支持 UCS-2 或 UTF-16 编码,并保持不变。

Azure SQL 数据库和 Azure SQL 托管实例还支持数据库和列级别的 UTF-8,而 SQL 托管实例也在服务器级别支持 UTF-8。

UTF-8 与 UTF-16 的存储差异

Unicode 联盟为每个字符都分配一个唯一码位(介于 000000-10FFFF 之间的值)。 使用 SQL Server 2019 (15.x) 时,UTF-8 和 UTF-16 编码都可用来表示整个范围:

  • 如果使用 UTF-8 编码,ASCII 范围(000000-00007F)内的字符需要 1 个字节,介于 000080 和 0007FF、000800 和 00FFFF 以及 0010000 和 0010FFFF 之间的码位分别需要 2、3 和 4 个字节。
  • 如果使用 UTF-16 编码,介于 000000 和 00FFFF 以及 0010000 和 0010FFFF 之间的码位分别需要 2 和 4 个字节。

下表列出了各个字符范围和编码类型的编码存储字节:

展开表
代码范围(十六进制) 代码范围(十进制) 使用 UTF-8 时的存储字节1 使用 UTF-16 时的存储字节1
000000–00007F 0–127 1 2
000080–00009F
0000A0–0003FF
000400–0007FF
128–159
160–1,023
1,024–2,047
2 2
000800–003FFF
004000–00FFFF
2,048–16,383
16,384–65,535
3 2
010000–03FFFF2

040000–10FFFF2
65,536–262,1432

262,144–1,114,1112
4 4

1存储字节是指编码字节长度,而不是数据类型在磁盘上的存储大小。 若要详细了解磁盘上的存储大小,请参阅 nchar 和 nvarchar,以及 char 和 varchar

2增补字符的码位范围。

提示

通常认为,在 CHAR(n) 和 VARCHAR(n) 或在 NCHAR(n) 和 NVARCHAR(n) 中,n 定义字符数 。 这是因为在示例 CHAR(10) 列中,可以使用排序规则(如 Latin1_General_100_CI_AI)存储在 0-127 范围内的 10 ASCII 字符,因为此范围内的每个字符仅使用 1 个字节。

但是,在 CHAR(n) 和 VARCHAR(n) 中,n 以字节数 (0-8,000) 定义字符串大小,而在 NCHAR(n) 和 NVARCHAR(n) 中,n 以字节对 (0-4,000) 定义字符串大小 。 n 不会定义可存储的字符数。

如你所见,选择适当的 Unicode 编码和数据类型可以节省大量存储或增加当前存储占用,具体视使用的字符集而定。 例如,如果使用启用了 UTF-8 的拉丁语排序规则(如 Latin1_General_100_CI_AI_SC_UTF8),则 CHAR(10) 列可存储 10 个字节,并且可保留 0-127 范围内的 10 ASCII 字符。 但只可保留 5 个 128-2047 范围内的字符和 3 个 2048-65535 范围内的字符。 相比之下,由于 NCHAR(10) 列存储 10 个字节对(20 个字节),因此该列可保留 10 个 0-65535 范围内的字符。

在选择是要将 UTF-8 编码还是 UTF-16 编码用于数据库或列前,请先考虑要存储的字符串数据的分布情况:

  • 如果它主要在 ASCII 范围 0-127 内(如英语),使用 UTF-8 和 UTF-16 时每个字符分别需要 1 个和 2 个字节。 UTF-8 具有存储优势。 如果使用已启用 UTF-8 的排序规则将包含在 0-127 范围内的 ASCII 字符的现有列数据类型从 NCHAR(10) 更改为 CHAR(10),则会减少 50% 的存储需求。 之所以会有这种减少是因为,NCHAR(10) 需要 20 个字节进行存储,而 CHAR(10) 相比则需要 10 个字节用于相同的 Unicode 字符串表示形式。
  • 如果超出 ASCII 范围(几乎所有拉丁字母语言以及希腊语、西里尔文、科普特语、亚美尼亚语、希伯来语、阿拉伯语、叙利亚语、它拿语和西非书面文),使用 UTF-8 和 UTF-16 时每个字符都需要 2 个字节。 在这种情况下,可比较的数据类型(例如,char 与 nchar 之间)没有显著的存储差异。
  • 如果它主要是东亚语言(如韩语、中文和日语),使用 UTF-8 和 UTF-16 时每个字符分别需要 3 个和 2 个字节。 UTF-16 具有存储优势。
  • 使用 UTF-8 和 UTF-16 时,介于 010000 和 10FFFF 范围内的字符都需要 4 个字节。 在这种情况下,可比较的数据类型(例如,char 与 nchar 之间)没有存储差异。

有关其他注意事项,请参阅编写国际化 Transact-SQL 语句

转换为 UTF-8

因为在 CHAR(n) 和 VARCHAR(n) 或在 NCHAR(n) 和 NVARCHAR(n) 中,n 定义字节存储大小,而不定义可以存储的字符数,所以确定必须转换的数据类型大小很重要,这可以避免数据被截断 。

例如,考虑定义为 NVARCHAR(100) 的列,该列存储了 180 个字节的日语字符。 在本示例中,当前使用 UCS-2 或 UTF-16 对列数据进行编码,每个字符使用 2 个字节。 将列类型转换为“VARCHAR(200)”不足以防止数据被截断,因为新的数据类型只能存储 200 个字节,而使用 UTF-8 编码时,日语字符需要 3 个字节。 因此,必须将列定义为 VARCHAR(270),以避免由于数据截断而丢失数据。

因此,在将现有数据转换为 UTF-8 之前,需要事先知道列定义的预计字节大小,并相应地调整新数据类型的大小。 请参阅数据示例 GitHub 中的 Transact-SQL 脚本或 SQL 笔记本,其中使用 DATALENGTH 函数和 COLLATE 语句来确定现有数据库中 UTF-8 转换操作的正确数据长度要求。

要更改现有表中的列排序规则和数据类型,请使用设置或更改列排序规则中所述的一种方法。

要更改数据库排序规则(默认允许新对象继承数据库排序规则)或更改服务器排序规则(默认允许新数据库继承系统排序规则),请参阅本文的相关任务部分。

[转帖]SQLServer的UTF8支持的更多相关文章

  1. 为Gradle添加UTF-8支持

    gradle默认使用系统字符编码,大多数中文系统是使用GBK编码 但程序员绝大部分都是使用UTF-8写各类java文件以及其他资源文件 编译时很容易报错,比如下面的错误: ”警告:编码 GBK 的不可 ...

  2. [转帖] sqlserver CAL 授权模式下 只能够有20个core的使用问题

    http://www.cnblogs.com/diabloxl/p/3623640.html?utm_source=tuicool&utm_medium=referral 公司这边性能组老师进 ...

  3. Source Insight 3.X utf8支持插件震撼发布

    继上次SI多标签插件之后,因为公司内部编码改为utf8编码,因此特意做了这个Source Insight 3.X utf8插件. 下载地址:[点我] 安装说明: 解压msimg32.dll sihoo ...

  4. [转帖]SQLSERVER的兼容级别

    SQL Server数据库的兼容级别 http://www.cnblogs.com/sosoft/archive/2017/07/08/sqljrjb.html 改天尝试一下 在SQLSERVER20 ...

  5. 使用的SQLServer版本不支持数据类型“datetime2“

    快速解决方法: 原因,在使用ado.net entity的时候,entity使用的数据库是sqlserver 2008, 但后来实际使用中使用的数据库是sqlserver 2005, 操作DateTi ...

  6. Source Insight 3.X utf8支持插件更新

    [更新内容] 修复了当UTF8文件外部改变时,SI无法检测到的bug. 实现 [下载地址] 点我 [计划] 未来(无限长)优化utf8编码检测规则,提高准确度.

  7. [转帖]SQLSERVER 使用触发器实现 禁用sa用户 在非本机登录

    原贴地址: https://blog.csdn.net/reblue520/article/details/51580102 具体的方法为: 创建一个触发器 CREATE TRIGGER forbid ...

  8. [转帖]SQLSERVER 查看服务器信息的命令

    SELECT SERVERPROPERTY('ServerName') AS ServerName SELECT SERVERPROPERTY('BuildClrVersion') AS BuildC ...

  9. SQLServer客户端连接工具(支持2000,20005,2008)

    绿色版本, 体积小(不到2M), 支持数据库版本2000 2005 2008 界面仿最经典的SQLServer2000: 下载地址:http://download.csdn.net/detail/gg ...

  10. [转帖]Sqlserver BCP 的用法

    SQL Server中bcp命令的用法以及数据批量导入导出 http://www.cnblogs.com/xwdreamer/archive/2012/08/22/2651180.html 我这边使用 ...

随机推荐

  1. [研究]SpringBoot-MybatisPlus-Dynamic(多数据源)

    SpringBoot-MybatisPlus-Dynamic(多数据源) 前言 ​ 基于工作上班累死了...打开自己电脑 不知道干些啥 就康康 PL 网站康康 更新了啥 ​ 咦~~~还挺多 看到了多数 ...

  2. Linux驱动开发笔记(六):用户层与内核层进行数据传递的原理和Demo

    前言   驱动作为桥梁,用户层调用预定义名称的系统函数与系统内核交互,而用户层与系统层不能直接进行数据传递,进行本篇主要就是理解清楚驱动如何让用户编程来实现与内核的数据交互传递.   温故知新 设备节 ...

  3. Python——第五章:模块(Module)、自定义模块、第3方开源模块、包(Package)

    什么是模块(Module)? 在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护. 为了编写可维护的代码,我们把很多代码按功能分组,分别放到不同的文件里,这 ...

  4. Docker + Jenkins 如何实现自动化部署?

    Docker + Jenkins 如何实现自动化部署? 一. 概述 实验室每次项目发布测试时,都要手动本地打包好了然后上传到服务器,替换原来nginx下面的目录文件,十分麻烦和繁琐.这次就来优化一下, ...

  5. 一些JavaSE学习过程中的思路整理(三)(主观性强,持续更新中...)

    目录 一些JavaSE学习过程中的思路整理(三)(主观性强,持续更新中...) Java线程同步的几种常见情况分析 由简单到复杂的几种单例模式写法 死锁的实现与破解 使用lambda表达式化简代码 J ...

  6. 实例讲解将Graph Explorer搬上JupyterLab

    摘要:基于 Graph Explorer 在 Jupyter 上进行图探索,可以大大降低编码成本,丰富 JupyterLab 的数据表现力. 本文分享自华为云社区<将 Graph Explore ...

  7. centos8 测地卸载php5.6 与卸载php7

    centos8 yum php 默认安装 php7.1.2 我想卸载php7 ,安装php5.6 yum remove php 无法彻底卸载干净.必须强制删除,使用下面命令查看全部php软件包 rpm ...

  8. 实用指南:手把手搭建坚若磐石的DevSecOps框架

    长期以来,安全问题一直被当作软件开发流程中的最后一步.开发者贡献可以实现软件特性的代码,但只在开发生命周期的测试和部署阶段考虑安全问题.随着盗版.恶意软件及网络犯罪事件飙升,开发流程需要做出改变. 开 ...

  9. ByConity 社区回顾|ByConity 和开发者们一起展望未来,携手共进!

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 新年伊始,我们想在这里感谢一群 ByConity 社区的小伙伴们. 正是因为有社区的开发者的支持,截止到 2023 ...

  10. IIS 设置超时时间

    高级设置 => 限制 => 连接超时(秒),默认120秒,根据实际情况调整