首页 > 其他分享 >凡是有但是-varchar和nvarchar的初步学习之一

凡是有但是-varchar和nvarchar的初步学习之一

时间:2023-12-24 09:00:12浏览次数:26  
标签:字符 varchar 编码 数据库 字符集 凡是 nvarchar

凡是有但是-varchar和nvarchar的初步学习之一


背景

高应用开发, 在涉及到国内国外的问题时,重要的事情有两个:
时区转换, 字符集转换. 

时区转换虽然是很难理清楚, 各种规范不统一的事情
但是字符集转换更加扯淡. 

如果是一种数据库,一种字符集可能还好说
现在面临的是 多种数据库: 开源,商业,信创,分布式...
这时候就已经是一头雾水了. 
自己虽然看了一阵子, 但是依旧是迷迷糊糊的.
所以想先总结一下, 希望后续能够慢慢的将内容夯实

varchar和nvarchar

数据库有varchar和nvarchar
其实一个比较重的区别是:
部分数据库 varchar 后面的数字指的是 这个字段能够存储的字节数.
nvarchar 后面的数字, 基本上指的是能够存储的字符数. 

这里就有一个 凡是有但是. 
Mysql8数据库虽然有 varcahr和nvarcahr, 但是他计算长度限制是按照字符数来进行计算. 
所以就引入了 mysql utf8mb3 和 utf8mb4 下数据库varcahr总长度限制的问题. 

另外神通数据库有这么一个参数, 可以指定varchar的长度限制.  
DEFAULT_VARCHAR_LEN=1
会改变varchar的存储情况. 

Oracle和MySQL的限制问题

SQLServer的限制: 注意我的排序规则是 chinese_prc_ci_as 
varchar时: 
消息 131,级别 15,状态 2,第 6 行
The size (8001) given to the column 'zhaobsh' exceeds the maximum allowed for any data type (8000).
nvarchar时: 
消息 2717,级别 16,状态 2,第 7 行
The size (8000) given to the parameter 'zhaobsh' exceeds the maximum allowed (4000).

数据库会有一些底层的限制

Oracle数据库一开始与SQLServer的限制是一样的 
也是在ZHS16GBK的字符集  varchar(8000) nvarchar(4000)
但是Oracle19c 时进行了一定程度的扩张: 
32767 bytes if MAX_STRING_SIZE = EXTENDED
4000 bytes if MAX_STRING_SIZE = STANDARD

但是据说这个参数修改起来很麻烦:
数据库需要 startup UPGRADE 以升级模式启动,
然后才能修改参数,
alter system set MAX_STRING_SIZE = EXTENDED scope=spfile;
并且需要跑脚本 utl32k.sql,
然后关闭数据库再正常重启数据库。

注意这里面有一个深坑, 如果不改这个参数 oracle12c 以后可以创建一个 3万多长度的varchar列
但是插入数据时 就会被截断到 4000 / 80000 的长度. 

关于字符编码

需要说明, 字符集是字符集, 字符编码格式是字符编码格式. 
只不过国内的 GB2312 GBK GB18030 既是字符集,又是编码格式. 
所以很多人有所混淆. 

unicode 是字符集, 用来进行全世界所有字符的展示
utf-8 是编码格式,用于计算机系统进行存储. 
utf-16 utf-32 是另外两种编码格式, 不通电是针对字符长度的限制是不一样的. 

字符编码的特点

广义的 Unicode 是一个标准,定义了一个字符集以及一系列的编码规则,
即 Unicode 字符集和 UTF-8、UTF-16、UTF-32 等等编码……

Unicode 字符集为每一个字符分配一个码位,例如「知」的码位是 30693,记作 U+77E5(30693 的十六进制为 0x77E5)。
UTF-8 顾名思义,是一套以 8 位为一个编码单位的可变长编码。会将一个码位编码为 1 到 4 个字节:

U+ 0000 ~ U+ 007F: 0XXXXXXX
U+ 0080 ~ U+ 07FF: 110XXXXX 10XXXXXX
U+ 0800 ~ U+ FFFF: 1110XXXX 10XXXXXX 10XXXXXX
U+10000 ~ U+1FFFF: 11110XXX 10XXXXXX 10XXXXXX 10XXXXXX

根据上表中的编码规则,之前的「知」字的码位 U+77E5 属于第三行的范围:

       7    7    E    5    
    0111 0111 1110 0101    二进制的 77E5
--------------------------
    0111   011111   100101 二进制的 77E5
1110XXXX 10XXXXXX 10XXXXXX 模版(上表第三行)
11100111 10011111 10100101 代入模版
   E   7    9   F    A   5

这就是将 U+77E5 按照 UTF-8 编码为字节序列 E79FA5 的过程。反之亦然。

varchar与nvarchar解决的问题

varchar 应该只是按照数据库的字符集进行文件的存储, 只能够存储编码格式,字符集,排序规则内的字符
无法保存非自己字符集内的字符. 

nvarchar 则是将字符按照unicode 等格式进行保存. 
这样的话, 能够保证非标准字符集支持的字符进行展示. 

一定程度下可以实现国际化多语的需求.

其他数据库的情况

PG数据库没有 nvarchar 
他的字符类型就是 varchar char 还有 text 
他应该默认使用utf8国际化支持, 然后 数字表示的是字符长度.

mysql数据库 有nvarchar的类型
但是他的varchar 也是按照字符进行存储, 理论上也是字符, 不是字节. 
mysql的坑在于 utf8mb3和 utf8mb4 

国产数据库里面要看支付的字符集. 
国产信创必须要支持GB18030字符集. 
但是GB18030与UTF8应该不是严格意义上的子集和超集的关系
所以很多表现也与字符集有关系.

UTF8的出现其实比很多数据库的出现要晚一些.
SQLServer其实到了2019的版本才严格支持 utf8 
因为微软的国际化做的其实比utf8要更久和更踏实, 其实sqlserver的历史包袱也是最大的. 

标签:字符,varchar,编码,数据库,字符集,凡是,nvarchar
From: https://www.cnblogs.com/jinanxiaolaohu/p/17923983.html

相关文章

  • Mysql Varchar(n) 占用字符、字节数浅析
    一、概述varchar(n)括号中的n代表最大可容纳的字符的个数,注意,并不是代表字节的个数一个中文和一个英文都是一个字符,只不过mysql的编码格式不同时,一个英文和一个中文所占用的存储字节数不同,一个英文字符占用的字节数是1,中文字符和英文字符不同,以下是常用的编码格式......
  • MySQL字段的字符类型该如何选择?千万数据下varchar和char性能竟然相差30%?
    MySQL字段的字符类型该如何选择?千万数据下varchar和char性能竟然相差30%?前言上篇文章MySQL字段的时间类型该如何选择?千万数据下性能提升10%~30%......
  • 数据库的三大范式;varchar与char的区别
    一、数据库的三大范式1.1第一范式数据表中的每一列(每个字段)都不可以再拆分。例如用户表,用户地址还可以拆分成国家、省份、市,这样才符合第一范式。1.2第二范式在第一范式的基础上,非主键完全依赖于主键,而不能是依赖于主键的一部分。例如订单表里面,存储了商品信息(商品价格、商品类型),那......
  • CHAR与VARCHAR如何选择
    在CHAR和VARCHAR的选择上,这些情况下使用VARCHAR是合适的:字符串列的最大长度比平均长度大很多,列的更新很少;使用了像UTF-8这样复杂的字符集,每个字符都使用不同的字节数进行存储。CHAR适合存储很短的字符串,或者所有值定长或都接近同一个长度。例如,CHAR非常适合存储密码的MD5值,因为这是......
  • Oracle 12C 新特性-扩展数据类型,在12c中,与早期版本相比,诸如VARCHAR2, NAVARCHAR2以及
    1.查看参数max_string_size默认值SQL>showparametermax_string_sizeNAME                   TYPE                 VALUE---------------------------------------------------------------------......
  • nvarchar和varchar的区别
    nvarchar和varchar的区别Unicode字符集就是为了解决字符集这种不兼容的问题而产生的,它所有的字符都用两个字节表示,即英文字符也是用两个字节表示如果还为了这个纠结,就直接看看后面的解说,做决定吧。一般如果用到中文或者其它特殊字符,我就会使用n开头的类型,否则的话直接使用var开头的......
  • springjdbc处理nvarchar
    当我们使用spring-jdbc来做持久化时(注意不是spring-data-jbc),有时候一些特殊字符存入数据库时会用到nvarchar、nvarchar2这种类型(比如存放化学式,如CO₂等),默认会直接按照String类型来处理字段类型映射,如果要最终让使用ps.setNString这种,一般有几种办法。当使用JdbcTemplate时,可以......
  • - csrf跨站请求的相关装饰器 - Auth模块的使用 - 凡是跟登录、注册、修改密码、注销
    csrf跨站请求的相关装饰器 Django中有一个中间件对csrf跨站做了验证,我只要把csrf的这个中间件打开,意味着所有的方法都要被验证在所有的视图函数中:只有几个视图函数做验证只有几个函数不做验证csrf_protect:哪个视图函数加了这个装饰器,这个函数就会做验证 csrf_exemp......
  • MySQL中char与varchar的区别:存储机制、性能差异、适用场景
    引用链接:https://www.maoyingdong.com/mysql-char-vs-varchar/ 在MySQL中,varchar和char都可以用来存储字符串。从语义上看,varchar是变长的(Variable-length),char是定长的(Fixed-length)。本文基于MySQL5.7版本,从varchar和char的语义,到存储引擎底层存储机制,探讨它们在存......
  • MySQL在线修改varchar列的注意事项和方法
    在数据库管理中,altertable操作是修改数据库结构的关键部分。mysql从5.6版开始提供在线操作,提供了一种在不锁定表的情况下执行这些更改的便捷方法。不过,这也有一些注意事项。在本文中,将探讨在线修改varchar列的过程,深入了解在扩大此类列的大小时获得的启发。假设有以下表定义,该表......