首页 > 数据库 >不能坐视了!Oracle数据库varchar2字段扩容,每月总有那么一两次。----- 优秀的程序应总是能规避问题

不能坐视了!Oracle数据库varchar2字段扩容,每月总有那么一两次。----- 优秀的程序应总是能规避问题

时间:2024-01-29 21:00:14浏览次数:18  
标签:nvarchar2 name varchar2 64 mer Oracle -----

Oracle数据库varchar2字段扩容-始末

今天,有后端小伙伴提了个sql工单。对我司服务商系统Oracle数据库的一个mer_name字段扩容。

alter table T_MER_SETTLE modify mer_name VARCHAR2(100)

审批前,我查了一下当前这个mer_name字段的长度是 VARCHAR2(64)。

基于对我司客户名称的长度通常不超过64字的了解,我下意识里感到奇怪:莫非存在长度超过64个文字的客户名称?这种情况应该很少吧?什么公司的名字能有这么长呢?

 

然后,我找当时人来询问。他言说,当时开发需求时,看到企业表里的mer_name是varchar2(100),依据对系统里企业名称长度通常不会超过64个汉字的认识,就把新表的mer_name定义为varchar2(64)。 今天生产环境的告警显示,在向这个T_MER_SETTLE表插入数据时出现“字段值超长”持久化失败的bug,这才得知Oracle的varchar2(64)与mysql的varchar(64)不同,mysql的varchar(64)能存最多64个字符,而Oracle的varchar2(64)则不同。在数据库字符集是UTF-8的情况下,varchar2在存汉字时,是每个汉字占3个字节。也就是说,这个varchar2(64)最多可以存64/3=21个汉字。

 

本着解决问题优先的原则,我审批了sql工单并执行sql。

 

优秀的程序应总是能规避问题

字段扩容,这是我们日常开发中经常遇到的小事。我们服务商系统类似对varchar2字段扩容的案例,几乎每月都发生。那么,针对这个字段扩容,大家有没有琢磨过,我们如何在开发时就能规避呢?

优秀的程序应总是能规避问题。我们来复盘一下这个事情。

有必要先说明一个情况,我司绝大多数系统以mysql数据库为主,服务商系统是其中唯一一个使用Oracle数据库的小众系统。并且,服务商系统的日常维护或需求迭代较少,由我们技术团队中的三个同学抽一部分精力兼管。 因此,大家对Oracle数据库了解的并不多,相比mysql,就少多了。

好,继续来复盘。
开发人员不了解varchar2这个技术点,凭着mysql数据库经验和对业务的了解,定义了  mer_name VARCHAR2(64) 。
我审批时,也不了解varcahr2这个技术点,就去反问开发同学。同样,其他同学,也未必清楚Oracle的varchar2这个数据类型的细节。

 

那么,如何规避呢?

无药可救了吗?

不!

我们事后了解到,Oracle的nvarchar2不区分字符类型,它将汉字、全角符号与数字、字母、半角符号等均视为一个字符。也就是说,nvarchar2(64)表示可存最大64个字符。注意这里不是字节,而是字符。 包括 数字、字母、符号、以及汉字。同时,在存储含有文字的字段时,Oracle开发规范里建议使用nvarchar2取代varchar2。

因此,我们可以做什么?

将数据库里的mer_name的数据类型全部改为nvarchar2,以及其他的这种varchar2字段类型使用不当的字段。

这以后,服务商系统再有迭代开发时,开发者CV时,就不会(或很少)再有varchar2的mer_name了,乐观一点讲,再出现因varchar2数据类型使用不当而导致“字段值超长”持久化失败的bug就会扼杀在摇篮里。

 

【附】Oracle数据类型varchar2与nvarchar2

  1. varchar - Oracle不建议使用varchar类型(我在DBeaver中新建varchar字段时自动建成了varchar2,无论是所见即所得的操作方式,还是执行DDL方式)
  2. varchar2 - varchar2(20) 表示可存最大20个字节长度的字符串。 数字/字母/半角符号 占一个字节。 对于全角符号或汉字,则要看字符集,GBK的话,一个汉字占2个字节;UTF-8的话,一个汉字占3个字节。
  3. nvarchar - Oracle中没有nvarchar这个数据类型
  4. nvarchar2 - nvarchar2(20) 表示可存最大20个字符。注意这里不是字节了,而是字符。 包括 数字、字母、符号、以及汉字。每个字符占2个字节存储。
 
  • varchar2是Oracle提供的特定数据类型,Oracle可以保证varchar2在任何版本中该数据类型都可以向上或向下兼容。
  • nvarchar2虽然更占空间,但是他有更好的兼容性。尤其是当字段包含汉字的情况下,推荐使用nvarchar2。  - - - - - - - - 我们服务商系统Oracle数据库里,对于mer_name等包含汉字的字段,大家往往沿袭使用varchar2(100甚至更大),我们在新建表里涉及到这个字段时,有开发者会误以为Oracle的varchar2与mysql里的varchar相同,我们mysql应用里约定mer_name是varchar(32) ,就在Oracle库里定义成了 varchar2(32) ,结果,服务商系统在生产运行过程中,出现插入mer_name因字段值超长而持久化数据库失败。 - - - - - - - - 优秀的程序应总是能规避问题。因此,以后在服务商系统里,当定义包含汉字的字段时,使用 nvarchar2,而非 varchar2。 因此,在服务商系统作为我司系统的小众系统的背景下,Oracle的技术特性我们不一一晓知是可以理解和接受的。而如何在不一一晓知这些技术特性的情况下,能够规避这些技术特性带来的bug,需要我们引起思考和实践摸索。
 

 【附】字段值超长,程序异常截图↓

 

标签:nvarchar2,name,varchar2,64,mer,Oracle,-----
From: https://www.cnblogs.com/buguge/p/17995321

相关文章

  • 从嘉手札<2024-1-29>
    补一下以前的几篇日记2018-4-6当一个人不在纠结没有什么而是开始珍视他所拥有的一切的时候才算得上真正的成熟个人的意志不能因受到社会的压力而软弱也不能受到自然的压力而萎缩而应当如冬日里的松柏笔直轩昂,凌然傲立2018-4-9又是一夜的噩梦袭扰浓雾弥漫的清晨正如鬼......
  • 初识Jjava --数组
    Day6publicstaticvoidmain(String[]args){int[]nums;//定义一个数组nums=newint[10];nums[0]=1;nums[1]=2;nums[2]=3;nums[3]=4;nums[4]=5;nums[5]=6;nums[6]=7;nums[7]=8;......
  • Oracle
    一、Oracle数据库1.1、基本介绍Oracle数据库的一个基本任务是存储数据。Oracle数据库服务器是由一个数据库和至少一个数据库实例组成。数据库是一组存储的文件,而数据库实例是一组管理数据文件的内存结构。另外,数据库由后台进程组成。一个数据库和一个实例是紧密相连的,因此术语-......
  • 无涯教程-Swift - Generics(泛型)
    Swift4语言提供"Generic"函数来编写灵活且可重用的函数和类型,泛型用于避免重复并提供抽象,Swift4标准库是使用泛型代码构建的。Swift4s的"Arrays"和"Dictionary"类型属于Generic集合。funcexchange(a:inoutInt,b:inoutInt){lettemp=aa=bb=temp}varn......
  • v-contextmenu
    v-contextmenu-npm(npmjs.com)npmiv-contextmenu@3.1.1--save-devnpminstall--savevue-runtime-helpers#main.tsimportcontentmenufrom'v-contextmenu'import"v-contextmenu/dist/themes/bright.css";#myTree.vue<template&......
  • go-cache基于内存的键值存储缓存库
    Go的内存key:valuestore/cache(类似于Memcached)库,适用于单机应用程序。文档https://pkg.go.dev/github.com/patrickmn/go-cachehttps://github.com/patrickmn/go-cachehttps://patrickmn.com/projects/go-cache/安装gogetgithub.com/patrickmn/go-cache方法funcN......
  • 登录认证-完成(拦截器)
    //JWT令牌生成,工具类packagecom.di.bigevent.utils;importcom.auth0.jwt.JWT;importcom.auth0.jwt.algorithms.Algorithm;importjava.util.Date;importjava.util.Map;publicclassJwtUtil{privatestaticfinalStringKEY="itheima";/......
  • 数论1-素数
    Part1前置记号约定整数集合:$\Z={...,-2,-1,0,1,2,…}$自然数集合:\(\N=\{0,1,2,…\}\),下文若不特殊说明,则出现的所有字母皆代表自然数。整除:若\(a=b\timesk\),则\(b\)整除\(a\),记作\(b\mida\),否则记作\(b\nmida\)约数:若\(b\mida\)且\(b\g......
  • Django - admin 表单编辑页面,增加自定义功能,前端上传视频到oss
    #背景:可以在admin编辑页面原有基础上,增加一些可定制的功能,如:在本地上传图片到oss,减少服务器的带宽压力,下面就以此为例。示例图:  一。models.py#video可以直接用字符串存储,因为最终里面只有有一串oss的视频路径classNews(models.Model):OSS_URL='https://xxxx......
  • notepad怎么保存utf-8格式 菜单栏"编码”下拉菜单中选择“UTF-8” 或者Encoding选择 U
    notepad怎么保存utf-8格式菜单栏"编码”下拉菜单中选择“UTF-8”或者Encoding选择UTF-8,或者菜单栏-格式->以UTF-8无BOM格式编码要在Notepad中保存UTF-8格式,可以按照以下步骤操作:1.打开Notepad,然后新建一个文本文档。2.将要保存为UTF-8格式的文本复制粘贴到Notepad中。3.点......