事情是这样的…
在做项目评审时,表定义基本都会涉及到char、varchar2类型的使用。在看到char类型时,我都会多说一句:“这个字段长度后期有没有变更的可能,如果有建议用varchar类型;如果没有则保持char类型;如果是char(1),则建议char(2)增加一位长度,将值“1”扩展为“01”,现在不变的长度,给未来一个可变的机会。”
最近就遇到一个char(1)增加长度的需求发布,当时我以为开发清楚char的特性呢,也就没有多嘴提醒,于是直接变更成了char(2)。改完没有5分钟,开发就过来找我:“哥,不对啊,怎么我取的状态值不对,原来的状态值都多了个空格,我这程序判断出问题了。”我无语道:“CHAR是定长类型,无论实际存储内容长度如何,都会占用定义时指定的固定空间(不足部分用空格填充),这个常识你不知道。”这我才意识到,我们认为的常识仅限于DBA圈,看来不定期的常识培训还是很有必要的。
于是做了紧急修复,先将char(2)类型改为varchar2(2)类型,从定长类型改为可变类型:VARCHAR2是变长类型,仅占用实际存储内容所需的空间。但前面旧的数据依然有空格,于是只能先空格剔除。
- 正则表达式剔除空格,只取数字查看长度
SELECT length(REGEXP_SUBSTR(status, '[0-9]+')) FROM t1;
- 使用merge进行update更新
MERGE INTO t1 as a
USING t1 as b
ON (a.id = b.id )
WHEN MATCHED THEN
UPDATE SET a.status = REGEXP_SUBSTR(b.status, '[0-9]+');
终于解决了这个紧急事故,万幸的是这个功能影响范围可控。看来有必要给领导申请做一次常识性的培训了,个人能力终归是有限的总会有遗漏,把知识点普及后把常识变为共识。我的DBA工作就可以“喝着咖啡听着歌”了,虽然这是理想状态,为了理想而努力。
共识第一步:知识点总结
| 维度 | CHAR | VARCHAR2 |
|---|---|---|
| 存储策略 | 定长(空格填充) | 变长(按需分配) |
| 空间效率 | 固定长度数据高效,变长数据浪费 | 所有场景均高效 |
| 尾部空格处理 | 存储时添加,检索时去除(select 填充空格 from 表 where 条件剔除尾部空格) | 严格保留 |
| 适用场景 | 编码、哈希值等固定长度小字段 | 文本、描述等长度不定的数据 |
| Oracle推荐度 | 仅用于严格的定长数据 | 主流选择,优先使用 |
共识第二步:测试小案例
-- 建表
CREATE TABLE t (
fixed_id CHAR(10),
dynamic_desc VARCHAR2(50)
);
-- 插入数据:‘a’,‘Hello+3个空格’
INSERT INTO t VALUES ('a', 'Hello ');
commit;
- 查看存储长度

- 查看char检索情况




- 查看varchar2检索情况


- 正测表达式:剔除空格

共识已达成
- 楼下买杯咖啡,打开音乐软件,开始今天愉快的工作。
欢迎赞赏支持或留言指正

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




