PG数据库存储验证

发布时间 2023-12-24 23:09:57作者: 济南小老虎

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

但是没太有具体的证据 , 今天已经很晚了, 想先休息改天继续研究.