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

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

时间:2024-01-03 14:05:42浏览次数:25  
标签:字符 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://blog.51cto.com/u_11529070/9084329

相关文章

  • [2023年度回顾总结]凡是过往,皆为序章
    原创/朱季谦2023年12月初,傍晚,在深圳的小南山看了一场落日。那晚我们坐在山顶的草地上,拍下了这张照片——仿佛在秋天的枝头上,结出一颗红透的夕阳。这一天很快就会随着夜幕的降临,化作记忆的碎片,然而,总会有一些难忘的痕迹,在逐渐落满灰尘的回忆里,熠熠生辉。这些痕迹,或许是一张随手......
  • MySQL对所有的表增加一个biz_e varchar255,如何快速实现?
    --先在数据库中创建一个存储过程DELIMITER//--先在数据库中创建一个存储过程DELIMITER//CREATEPROCEDUREAddBizEToTables()BEGINDECLAREdoneINTDEFAULT0;DECLAREtableNameVARCHAR(255);DECLAREcurCURSORFORSELECTtable_name......
  • 神通数据库的varchar和nvarchar的验证
    神通数据库的varchar和nvarchar的验证登录神通数据库isql注意神通数据库的默认密码是szoscar55Welcometoisql2.0.56interactiveterminal,ClientDefaultEncodingisUTF8.Logintime:2023-12-2516:00:36Passwordfordefaultuser:Connectto:神通数据库7.0......
  • ZHS16GBK字符集下面Oracle数据库varchar与nvarchar的验证
    ZHS16GBK字符集下面Oracle数据库varchar与nvarchar的验证背景周末分析了SQLServermysql等数据库想着继续分析一下oracle数据库这边oracle使用的是ZHS16GBK的字符集.所以比较特殊.还是建议得使用UTF-8字符集.能让系统干的活就让系统干,自己干国际化太费劲了.处......
  • 达梦数据库varchar和nvarchar的验证
    达梦数据库varchar和nvarchar的验证测试SQLcreatetablespacezhaobshdatafile'/opt/dmdbms/data/DAMENG/zhaobsh.dbf'size128#需要注意达梦数据库的大小限制为:#第1行附近出现错误[-2422]:数据文件[/opt/dmdbms/data/DAMENG/zhaobsh.dbf]大小无效,取值范围为(128~671......
  • MYSQL varchar和nvarchar一些学习
    MYSQLvarchar和nvarchar一些学习背景先试用utfmb3的格式进行一下简单验证注意脚本都是一样的.createdatabasezhaobsh;usezhaobsh;createtablezhaobsh(zhaobshvarcharvarchar(30),zhaobshnvarcharnvarchar(30));insertintozhaobshvalues('123abc','1......
  • SQLServer的varchar与nvarchar的学习之二
    SQLServer的varchar与nvarchar的学习之二背景昨天简单总结了多种数据库varchar和nvarchar的区别与关系今天想着能够分析一下数据库文件.计划使用winhex查看数据文件,简单进行学习过程创建数据库和表,然后进行一些测试,进行简单测试判断.createdatabasezhaobshc......
  • 凡是有但是-varchar和nvarchar的初步学习之一
    凡是有但是-varchar和nvarchar的初步学习之一背景高应用开发,在涉及到国内国外的问题时,重要的事情有两个:时区转换,字符集转换.时区转换虽然是很难理清楚,各种规范不统一的事情但是字符集转换更加扯淡.如果是一种数据库,一种字符集可能还好说现在面临的是多种数......
  • Mysql Varchar(n) 占用字符、字节数浅析
    一、概述varchar(n)括号中的n代表最大可容纳的字符的个数,注意,并不是代表字节的个数一个中文和一个英文都是一个字符,只不过mysql的编码格式不同时,一个英文和一个中文所占用的存储字节数不同,一个英文字符占用的字节数是1,中文字符和英文字符不同,以下是常用的编码格式......
  • MySQL字段的字符类型该如何选择?千万数据下varchar和char性能竟然相差30%?
    MySQL字段的字符类型该如何选择?千万数据下varchar和char性能竟然相差30%?前言上篇文章MySQL字段的时间类型该如何选择?千万数据下性能提升10%~30%......