注册
达梦数据库字符集与大小写问题使用分析
专栏/培训园地/ 文章详情 /

达梦数据库字符集与大小写问题使用分析

娄心如 2023/10/09 6149 0 0
摘要

1.参数解释:

LENGTH_IN_CHAR

VARCHAR 类型对象的长度是否以字符为单位。

1:是,设置为以字符为单位时,定义长度并非真正按照字符长度调整,而是将存储长度值按照理论字符长度进行放大。

所以会出现实际可插入字符数超过定义长度的情况,这种情况也是允许的。

同时,存储的字节长度 8188 上限仍然不变,也就是说,即使定义列长度为8188 字符,其实际能插入的字符串占用总字节长度仍然不能超过 8188;

0:否,所有 VARCHAR 类型对象的长度以字节为单位

CHARSET

字符集选项。0 代表 GB18030;1 代表UTF-8;2 代表韩文字符集 EUC-KR

CHARSET=0代表使用GB18030,即一个中文两个字节。CHARSET=1代表使用UTF-8,即一个中文3个字节。

2.案例展示:

按照定义理解,我做了以下实验:

初始化实例: ./dminit PATH=/dm/data/ INSTANCE_NAME=GRP1_LOCAL_01 PAGE_SIZE=32 EXTENT_SIZE=32 LOG_SIZE=2048 CHARSET=0 LENGTH_IN_CHAR=N AUTO_OVERWRITE=2 SQL> CREATE TABLE TEST (ID INT,NAME VARCHAR(8)); 操作已执行 已用时间: 20.546(毫秒). 执行号:59400. SQL> INSERT INTO TEST VALUES (1,'娄心如'); 影响行数 1 已用时间: 0.697(毫秒). 执行号:59401. SQL> COMMIT; 操作已执行 已用时间: 2.728(毫秒). 执行号:59402. SQL> INSERT INTO TEST VALUES (2,'娄心如娄'); 影响行数 1 已用时间: 1.222(毫秒). 执行号:59403. SQL> COMMIT; 操作已执行 已用时间: 1.866(毫秒). 执行号:59404. SQL> INSERT INTO TEST VALUES (3,'娄心如娄心'); INSERT INTO TEST VALUES (3,'娄心如娄心'); [-6169]:列[NAME]长度超出定义. 已用时间: 1.314(毫秒). 执行号:0. SQL> INSERT INTO TEST VALUES (3,'娄心如娄L'); INSERT INTO TEST VALUES (3,'娄心如娄L'); [-6169]:列[NAME]长度超出定义. 已用时间: 0.370(毫秒). 执行号:0. SQL> SELECT DATA_LENGTH,NAME,LENGTH(NAME),LENGTHB(NAME) FROM TEST,DBA_TAB_COLUMNS WHERE TABLE_NAME='TEST' AND COLUMN_NAME='NAME';2 行号 DATA_LENGTH NAME LENGTH(NAME) LENGTHB(NAME) ---------- ----------- -------- ------------ ------------- 1 8 娄心如 3 6 2 8 娄心如娄 4 8 已用时间: 5.706(毫秒). 执行号:59407. 可以看出在字段长度为9时就报错超出长度,只存储了4个中文字符。
初始化实例: ./dminit PATH=/dm/data/ INSTANCE_NAME=GRP1_LOCAL_01 PAGE_SIZE=32 EXTENT_SIZE=32 LOG_SIZE=2048 CHARSET=0 LENGTH_IN_CHAR=Y AUTO_OVERWRITE=2 SQL> CREATE TABLE TEST (ID INT,NAME VARCHAR(8)); 操作已执行 已用时间: 14.944(毫秒). 执行号:59400. SQL> INSERT INTO TEST VALUES (1,'娄心如'); COMMIT; 影响行数 1 已用时间: 0.698(毫秒). 执行号:59401. SQL> 操作已执行 已用时间: 4.695(毫秒). 执行号:59402. SQL> INSERT INTO TEST VALUES (2,'娄心如娄'); COMMIT; 影响行数 1 已用时间: 0.473(毫秒). 执行号:59403. SQL> 操作已执行 已用时间: 3.560(毫秒). 执行号:59404. SQL> INSERT INTO TEST VALUES (3,'娄心如娄心'); COMMIT; 影响行数 1 已用时间: 0.483(毫秒). 执行号:59405. SQL> 操作已执行 已用时间: 1.993(毫秒). 执行号:59406. SQL> INSERT INTO TEST VALUES (3,'娄心如娄心如'); COMMIT; 影响行数 1 已用时间: 0.478(毫秒). 执行号:59407. SQL> 操作已执行 已用时间: 3.593(毫秒). 执行号:59408. SQL> INSERT INTO TEST VALUES (5,'娄心如娄心如娄'); COMMIT; 影响行数 1 已用时间: 0.484(毫秒). 执行号:59409. SQL> 操作已执行 已用时间: 5.337(毫秒). 执行号:59410. SQL> INSERT INTO TEST VALUES (5,'娄心如娄心如娄心'); COMMIT; 影响行数 1 已用时间: 0.516(毫秒). 执行号:59411. SQL> 操作已执行 已用时间: 3.734(毫秒). 执行号:59412. SQL> INSERT INTO TEST VALUES (5,'娄心如娄心如娄心如'); COMMIT; INSERT INTO TEST VALUES (5,'娄心如娄心如娄心如'); [-6169]:列[NAME]长度超出定义. 已用时间: 0.485(毫秒). 执行号:0. SQL> 操作已执行 已用时间: 0.247(毫秒). 执行号:59414. SQL> INSERT INTO TEST VALUES (5,'娄心如娄心如娄心R'); COMMIT; INSERT INTO TEST VALUES (5,'娄心如娄心如娄心R'); [-6169]:列[NAME]长度超出定义. 已用时间: 0.452(毫秒). 执行号:0. SQL> 操作已执行 已用时间: 0.212(毫秒). 执行号:59416. SQL> SELECT DATA_LENGTH,NAME,LENGTH(NAME),LENGTHB(NAME) FROM TEST,DBA_TAB_COLUMNS WHERE TABLE_NAME='TEST' AND COLUMN_NAME='NAME'; 2 行号 DATA_LENGTH NAME LENGTH(NAME) LENGTHB(NAME) ---------- ----------- ---------------- ------------ ------------- 1 8 娄心如 3 6 2 8 娄心如娄 4 8 3 8 娄心如娄心 5 10 4 8 娄心如娄心如 6 12 5 8 娄心如娄心如娄 7 14 6 8 娄心如娄心如娄心 8 16 6 rows got 可以看出在字段NAME可以存储8个中文字符,实际最大存储长度为16,是长度定义的2倍。
初始化实例: ./dminit PATH=/dm/data/ INSTANCE_NAME=GRP1_LOCAL_01 PAGE_SIZE=32 EXTENT_SIZE=32 LOG_SIZE=2048 CHARSET=1 LENGTH_IN_CHAR=N AUTO_OVERWRITE=2 SQL> CREATE TABLE TEST (ID INT,NAME VARCHAR(8)); 操作已执行 已用时间: 16.185(毫秒). 执行号:59400. SQL> INSERT INTO TEST VALUES (1,'娄心RU'); 影响行数 1 已用时间: 0.751(毫秒). 执行号:59401. SQL> COMMIT; 操作已执行 已用时间: 3.682(毫秒). 执行号:59402. SQL> INSERT INTO TEST VALUES (2,'娄心如'); INSERT INTO TEST VALUES (2,'娄心如'); [-6169]:列[NAME]长度超出定义. 已用时间: 0.429(毫秒). 执行号:0. SQL> SELECT DATA_LENGTH,NAME,LENGTH(NAME),LENGTHB(NAME) FROM TEST,DBA_TAB_COLUMNS WHERE TABLE_NAME='TEST' AND COLUMN_NAME='NAME'; 2 行号 DATA_LENGTH NAME LENGTH(NAME) LENGTHB(NAME) ---------- ----------- -------- ------------ ------------- 1 8 娄心RU 4 8 可以看出在CHARSET=1的情况下,一个中文占用3个字符,NAME只能存储两个中文两个英文字符,总长度8.
初始化实例: ./dminit PATH=/dm/data/ INSTANCE_NAME=GRP1_LOCAL_01 PAGE_SIZE=32 EXTENT_SIZE=32 LOG_SIZE=2048 CHARSET=1 LENGTH_IN_CHAR=Y AUTO_OVERWRITE=2 SQL> CREATE TABLE TEST (ID INT,NAME VARCHAR(8)); 操作已执行 已用时间: 14.705(毫秒). 执行号:59400. SQL> INSERT INTO TEST VALUES (1,'娄心RU'); COMMIT; 影响行数 1 已用时间: 0.656(毫秒). 执行号:59401. SQL> 操作已执行 已用时间: 4.171(毫秒). 执行号:59402. SQL> INSERT INTO TEST VALUES (2,'娄心如'); COMMIT; 影响行数 1 已用时间: 0.435(毫秒). 执行号:59403. SQL> 操作已执行 已用时间: 1.745(毫秒). 执行号:59404. SQL> INSERT INTO TEST VALUES (3,'娄心如娄心'); COMMIT; 影响行数 1 已用时间: 0.517(毫秒). 执行号:59405. SQL> 操作已执行 已用时间: 3.732(毫秒). 执行号:59406. SQL> INSERT INTO TEST VALUES (3,'娄心如娄心如'); COMMIT; 影响行数 1 SQL> INSERT INTO TEST VALUES (5,'娄心如娄心如娄'); COMMIT; 影响行数 1 已用时间: 0.437(毫秒). 执行号:59409. SQL> 操作已执行 已用时间: 3.470(毫秒). 执行号:59410. SQL> INSERT INTO TEST VALUES (5,'娄心如娄心如娄心'); COMMIT; 影响行数 1 已用时间: 0.446(毫秒). 执行号:59411. SQL> 操作已执行 已用时间: 4.574(毫秒). 执行号:59412. SQL> INSERT INTO TEST VALUES (5,'娄心如娄心如娄心如'); COMMIT; 影响行数 1 已用时间: 0.438(毫秒). 执行号:59413. SQL> 操作已执行 SQL> INSERT INTO TEST VALUES (5,'娄心如娄心如娄心如娄'); COMMIT; 影响行数 1 已用时间: 0.534(毫秒). 执行号:59417. SQL> 操作已执行 已用时间: 1.923(毫秒). 执行号:59418. SQL> INSERT INTO TEST VALUES (5,'娄心如娄心如娄心如娄L'); 影响行数 1 已用时间: 0.412(毫秒). 执行号:59419. SQL> COMMIT; 操作已执行 已用时间: 2.023(毫秒). 执行号:59420. SQL> INSERT INTO TEST VALUES (5,'娄心如娄心如娄心如娄LO'); 影响行数 1 已用时间: 0.417(毫秒). 执行号:59421. SQL> INSERT INTO TEST VALUES (5,'娄心如娄心如娄心如娄LOU'); INSERT INTO TEST VALUES (5,'娄心如娄心如娄心如娄LOU'); [-6169]:列[NAME]长度超出定义. 已用时间: 0.476(毫秒). 执行号:0. SQL> SELECT DATA_LENGTH,NAME,LENGTH(NAME),LENGTHB(NAME) FROM TEST,DBA_TAB_COLUMNS WHERE TABLE_NAME='TEST' AND COLUMN_NAME='NAME'; 2 行号 DATA_LENGTH NAME LENGTH(NAME) LENGTHB(NAME) ---------- ----------- -------------------------------- ------------ ------------- 1 8 娄心RU 4 8 2 8 娄心如 3 9 3 8 娄心如娄心 5 15 4 8 娄心如娄心如 6 18 5 8 娄心如娄心如娄 7 21 6 8 娄心如娄心如娄心 8 24 7 8 娄心如娄心如娄心如 9 27 8 8 娄心如娄心如娄心如娄 10 30 9 8 娄心如娄心如娄心如娄L 11 31 10 8 娄心如娄心如娄心如娄LO 12 32 可以看出,在CHARSET=1,可以存储3个中文字符的情况下,LENGTH_IN_CHAR=1,最终NAME字段实际存储长度为32,为定义长度的4倍。

3.总结

image.png

在使用GB18030作为字符集类型,且LENGTH_IN_CHAR为0时,只存储了4个中文字符,没有进行自动扩充。LENGTH_IN_CHAR为1时,实际最大存储长度为16,是长度定义的2倍;
在使用UTF-8作为字符集类型,且LENGTH_IN_CHAR为0时,只存储了两个中文字符加两个英文字符。LENGTH_IN_CHAR=1,实际最大存储长度为32,为定义长度的4倍。

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服