PG数据库存储验证
背景
最近学习了SQLServer数据库的varchar和nvarchar的存储
想到PG数据库其实没让选择字符集,也没有nvarchar
所以想学习一下nvarchar的使用情况
建表以及插入sql
su - postgres
psql
create database zhaobsh
\c zhaobsh
create table zhaobsh(zhaobsh varchar(30));
插入数据
insert into zhaobsh values ('123abc');
insert into zhaobsh values ('abcd赵1234');
insert into zhaobsh values ('abcde한국12345');
查看文件对应
select oid from pg_class where relname='zhaobsh'
下载文件到本地
下载winhex以及使用
https://www.lanzoux.com/iQBXbfxq8na
找了一个非官方的地址
下载直接打开文件就可以:
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F
00001FA0 61 62 63 64 65 ED 95 9C EA B5 AD 31 32 33 34 abcde頃滉淡1234
00001FB0 35 00 00 00 00 00 00 00 6E 31 00 00 00 00 00 00 5 n1
00001FC0 00 00 00 00 00 00 00 00 02 00 01 00 02 08 18 00
00001FD0 19 61 62 63 64 E8 B5 B5 31 32 33 34 00 00 00 00 abcd璧?234
00001FE0 6D 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 m1
00001FF0 01 00 01 00 02 08 18 00 0F 31 32 33 61 62 63 00 123abc
发现PG数据库跟SQLServer不一样他是逆序存放的.
第一个:
123abc 都是单字节使用
第二个:
然后是 abcd加上一个中文字符. 1234
E8 B5 B5
网上可以查到:
赵 Unicode (UTF-8) utf-8 E8B5B5
符合预期,但是使用了 3个字节的存储大小.
第三个:
ED 95 9C EA B5 AD
한국 Unicode (UTF-8) utf-8 ED959CEAB5AD
发现韩文其实也是 三个字节的存储 在UTF-8的里面
注意我这个选择的是:
https://www.haomeili.net/Code/DetailCodes
网站还是非常好的.
字段长度验证
zhaobsh=# insert into zhaobsh values ('赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵');
INSERT 0 1
zhaobsh=# insert into zhaobsh values ('赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵赵');
ERROR: value too long for type character varying(30)
zhaobsh=#
说明PG 其实是存储的是字符长度而不是字节长度
金额类型的验证
create table zhaobsh2 (zhaobsh2 decimal(19,3));
insert into zhaobsh2 values (1.1) ;
继续分析
发现原始的文件里面存放的全是 0 不知道decimal 到了哪个地方了.
第二次测试:
create table zhaobsh3 (zhaobsh31 varchar(10),zhaobsh32 decimal(19,3));
insert into zhaobsh3 values ('12345',9.999);
分析应该是:
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F
00001FF0 31 32 33 34 35 0F 80 81 09 00 06 27 00 00 00 12345 € '
怀疑是这几位数字表示了9.999
0F 80 81 09 00 06 27 00 00
为了继续验证.
我将金额填充满.
注意可以是 16位金额数.
insert into zhaobsh3 values ('1234567',9999999999999999.999);
显示为:
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F
00001F60 31 32 33 34 35 36 37 1B 83 81 0F 27 0F 27 0F 1234567 ? ' '
00001F70 27 0F 27 06 27 00 00 00 76 31 00 00 00 00 00 00 ' ' ' v1
00001F80 00 00 00 00 00 00 00 00 03 00 02 00 02 08 18 00
00001F90 0F
感觉后面很多位数都在进行金额的展示, 但是具体不太好判断.
理论上 decimail 使用四个字节表示 9个数字. 19,3的精度应该至少需要9个字节.
所以理论上应该是从 37 之后数 9个字节:
所以怀疑如下数字表示了 插入的数字
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F
00001F60 1B 83 81 0F 27 0F 27 0F ? ' '
00001F70 27 0F 27 06 27 00 00 00 76 31 ' ' ' v1
但是没太有具体的证据 , 今天已经很晚了, 想先休息改天继续研究.