之前的总结
1. 在GB18030的字符集下面,国产数据库,神通和达梦一致.
varchar和nvarcahr 存储 中文,韩语,英文和数字是没有区别的
都是按照GB18030的编码进行填充.
2. 开源数据库PG和MySQL存储的是UTF-8编码.
所以理论上也不会出现乱码. 但是需要注意mysql需要使用utf8mb4才可以.
3. 商业数据库ORACLE和SQLServer 使用 GBK 类型的字符集时会乱码
但是如果采用nvarchar字符集.
sqlserver: nvarchar 会存储unicode字符集的码字
Oracle: nvarchar 会存储UTF8/AL32UTF8的字符集下的汉字
4. 关于字符长度
达梦,oracle,sqlserver 默认情况下: varcahr 是字节数
其他数据库 varcahr和nvarchar保持一致都是 字符数.
关于字符长度的说明
第一部分: Oracle
1. Oracle的参数: nls_length_semantics
nls_length_semantics参数的值来决定varchar(100)中的100指的字节数还是字符数
2. Oracle的nvarchar总长度:
12c之前,取决于国家字符集设置
AL16UTF16:2000
UTF8:4000
从12.1开始,取决于两个设置 —— MAX_STRING_SIZE和国家字符集
16383 if MAX_STRING_SIZE = EXTENDED and the national character set is AL16UTF16
32767 if MAX_STRING_SIZE = EXTENDED and the national character set is UTF8
2000 if MAX_STRING_SIZE = STANDARD and the national character set is AL16UTF16
4000 if MAX_STRING_SIZE = STANDARD and the national character set is UTF8
第二部分: SQLServer
varchar [ ( n | max) ]
可变长度,非 Unicode 字符数据。n 的取值范围为 1 至 8,000。max 指示最大存储大小是 2^31-1 个字节.
varchar(n) 长度为 n 个字节的可变长度且非 Unicode 的字符数据。
n 必须是一个介于 1 和 8,000 之间的数值。存储大小为输入数据的字节的实际长度,而不是 n 个字节。
nvarchar(n) 包含 n 个字符的可变长度 Unicode 字符数据。
n 的值必须介于 1 与 4,000 之间。字节的存储大小是所输入字符个数的两倍。
需要注意: SQLServer nvarchar 字段里面存储的是 unicode 码 而不是 utf8 类型的编码格式后的码子.
第三部分: PG,MySQL
开源数据库依托于开源的unicode. 所以他们没有nvarchar的概念.
他们的字符串都是 varchar 没有 nvarchar.
PG不同版本使用不同的utf8的版本
mysql 通过utf8mb3和utf8mb4代表不同的字符字节数量.
需要说明 PG基本上不限制列总宽度.
但是MySQL限制两个宽度, 一个是严格模式下的8126, 另外一个是64KB页面情况下不能超过的总长度限制.
第四部分: 国产数据库
能够支持 87887 个字符的 GB18030-2022 的标准在2023.8.1 开始执行.
所以国产数据库其实本质上都应该满足这个国家标准.
为了与Oracle监控, 国产的达梦和神通数据库其实都有nvarchar的字段类型.
但是需要说明他的存储基本上也是使用 GB18030的标准.
可以支持四字节长度的 部分字符.
比如: 한국 简体中文(GB18030) GB18030 83 36 84 33 82 37 F4 30
需要说明GBK字符集是一个定长的字符集。他的处理起来性能比较好
GB18030需要判断第二个字节是否在0x30和0x39之间来判断是否四字节的字符
第五部分: 开源数据库:GaussDB
Gaussdb 应该没有nvarchar字段, 他的都是 character varying 的字段类型.
理论上是跟PG9.2一致, 使用的是utf8类型的存储.
Oceanbase 数据库, 是模仿的mysql数据库.
他没有了mysql对64k的长度限制, 也没有nvarchar相关的字段类型
都是通过varchar字段进行处理.
关于java setN的处理
SetNstring 和 SetString 其实是有很大区别的.
这一块应该通过jdbc的驱动进行分类处理.
Java内部一般采用utf16编码格式.
浏览器一般默认采用utf8的编码格式.
前端传递给java的一般是utf8的字符.
java 会将代码转换成utf16,然后发送给jdbc.
当java的utf16 直接使用SetString, 那么会根据数据库的字符集进行i18n的国际化转换.
如果是gbk字符集, 就会自动转换成gbk编码.
此时如果gbk展示不全,那么就会乱码
但是如果使用了 setNstring, 如果数据库采用了nvarchar的列类型
那么国际化的处理就不一一样了.
会根据i18n 分析 传入类型,
如果是Oracle的AL32UTF8那么就会存于对应UTF8的字符集的编码字段
如果是SQLSERVER,才会将原始的unicode存入对应列的编码字段中.
如果数据库地段还是 varchar, 那么就算使用了setN,那么依旧可能会乱码
因为数据库在进行解析式还是按照 定长字节进行分析. 在数据库看来还是乱码的.
文章转载自济南小老虎,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




