MySQL数据库 (五) MySQL表的约束(上),非空约束,默认值约束,零填充约束,主键约束,符合主键

目录

一、引入表的约束

[二、not null 非空约束](#二、not null 非空约束)

[三、default 默认值约束](#三、default 默认值约束)

[四、comment 列描述](#四、comment 列描述)

[五、zerofill 零填充约束](#五、zerofill 零填充约束)

[六、primary key 主键约束](#六、primary key 主键约束)

复合主键

七、总结


一、引入表的约束

上一篇文章中,我们学习了 MySQL 各类字段数据类型,我们清楚:数据类型本身就是最基础的字段约束,依靠类型限制数据格式、取值范围,非法数据会直接被数据库拦截。但仅靠数据类型做约束,管控规则比较单薄,很多业务层面的数据规范没法实现,比如邮箱不能重复、用户账号不能为空、主键自动编号这类需求,因此 MySQL 额外提供了表级别的约束,作为数据校验的补充规则。

我们之前在建表后执行desc 表名查看表结构时,表头里 Null、Key、Default、Extra 这几列,对应的内容正是各类约束的标识,这也直观说明:约束从建表阶段就已经绑定在字段上,用来精细化管控字段的数据写入规则。

从业务设计的角度来说,数据库是存储用户数据的最后一道防线,想要从底层守住数据规范、保障数据完整且符合业务预期,就不能只依赖数据类型的基础限制,必须搭配配套的表约束。约束的核心目标,就是从数据库层面强制校验数据,过滤不符合规则的数据,最终保障数据表的数据完整性与可预期性。

MySQL 日常开发里高频使用的约束一共分为多类,这里我们重点讲解:null/not null(空约束)、default(默认值约束)、comment(字段注释)、zerofill(零填充)、primary key(主键约束)、unique key(唯一约束)、auto_increment(自增约束)等常用规则,逐个拆解语法、实操案例与适用场景。

下面我们先来看第一个约束 --- 非空约束:

二、not null 非空约束

在正式讲解非空约束之前,我们首先要厘清 MySQL 里 NULL 和空字符串 '' 的区别,这也是理解非空约束的前提。和 C 语言中 NULL 代表数字 0 的定义不同,MySQL 中的 NULL 代表该字段没有任何数据、是空值,而空字符串''是字段已经存入内容,只不过内容为空字符,二者在存储和运算规则上完全不一样。

MySQL 字段默认的空属性是 NULL,也就是建表不额外声明约束时,字段默认允许存入空值。但在实际项目开发中,我们会尽量把核心字段设置为 NOT NULL 非空约束,核心原因在于 NULL 无法参与常规算术运算,就像示例里执行 select 1+NULL;,最终运算结果依旧返回 NULL,空值参与计算会直接导致统计、求和等业务 SQL 出错,为了规避这类运算异常,业务字段优先限制非空。
非空约束 not null 的作用是在建表时绑定在字段上,被添加该约束的字段,插入数据时不能写入 NULL 空值,如果插入语句不给这个字段赋值、或是主动填入 NULL,数据库会直接拦截这条数据、抛出报错,从数据库层面强制保证该字段一定存在有效数据。

举例:

下面我们结合一个常见的场景来理解非空约束,理解 NOT NULL的设计意义。比如在一张班级的信息表中,班级名称、教室是两条核心必填信息,缺少班级名称就无法区分班级,没有教室信息就无法确定上课地点,因此这两个字段不允许为空,此时我们就可以通过 NOT NULL 约束在数据库层面强制限制。

下面我们建表,创建 myclass 表,class_name 和 class_room 两个字段后添加 not null 约束,剩余 other 字段不添加约束,使用数据库的默认规则。建表结束后执行 desc myclass 查看表结构,能看到添加非空约束的字段在 Null 列标识为NO,代表禁止存入 NULL 空值,无约束的 other 字段 Null 列为YES,保持默认可空状态,此时就能直观的区分是否为空约束的差异。

我们再通过 show create table myclass\G 查看建表原生语句,没有指定约束的 other 字段自带DEFAULT NULL,含义是插入数据时若不给该字段传值,数据库自动填充 NULL 空值,这也是 MySQL 字段的默认配置。后续插入数据时,若不给 class_name 或 class_room 赋值、或是主动传入 NULL,数据库会直接抛出报错拦截数据,以此实现非空约束的校验效果,从底层规避关键字段空值带来的数据异常问题。

那怎么体现约束呢?

下面我们插入多组语句,class_name、class_room 带有 NOT NULL 非空约束,other 字段默认可为空。 首先执行第一条完整插入语句,class_name、class_room、other 三个字段全部传入有效值 '高三2班'、'101教室'、'普通班',所有字段数据都符合约束规范,这条数据顺利插入数据表,查询后可以完整看到三条字段的内容。

紧接着第二条插入语句,我们只给两个非空字段赋值 '高三3班'、'103教室' ,省略 other 字段的传参。因为 other 没有非空约束、默认配置 DEFAULT NULL,MySQL 在缺省赋值时会自动填充 NULL,语句正常执行入库,查表后能看到这条记录的 other 列显示为 NULL,这也印证了可空字段的默认填充规则。

之后我们做两条违规插入,用来体现非空约束的拦截作用。第一种场景,插入时只填写class_name,完全忽略 class_room 字段,数据库报错提示字段没有默认值,无法完成插入;第二种场景,主动给 class_room 传入 NULL 空值,直接触发cannot be null报错。两类报错本质一致:class_room 被 NOT NULL 约束限定,既不能缺省不传,也不能手动写入 NULL。

此时我们就能得出非空约束的核心作用:被 NOT NULL 修饰的字段,插入数据时必须提供有效内容,缺省或写入 NULL 都会被数据库拦截,从物理层面保证关键字段永远存在有效值,避免空值带来后续运算、统计异常。

三、default 默认值约束

下面我们继续学习 DEFAULT 默认值约束:

默认值约束的设计初衷,是针对业务中高频重复的数据:如果某个字段在绝大多数场景下都会填入同一个固定内容,我们在建表阶段就可以提前用 default 预先设定好默认数据。后续插入记录时,用户可以自主选择手动填写新值,也可以省略该字段的传参,由数据库自动填充预设的默认内容,简化高频重复字段的录入工作。

下面我们建表举例 :

我们创建表 t13,在建表 SQL 中一共定义了三个字段:name 字段添加 not null 非空约束,没有配置默认值;age 字段设置 tinyint unsigned default 18,约定年龄缺省时默认填入 18;gender 字段设置 char(1) default '男',约定性别缺省时默认填入字符男。建表完成后执行 desc t13 查看表结构,从结果表格能够清晰区分三个字段的约束差异。name 字段的 Default 列是空值,代表无默认配置;age 的 Default 栏标注 18、gender 的 Default 栏标注男,正是我们在建表语句里通过 default 关键字预先配置的默认内容,这也直观体现:字段只要绑定了 default 约束,在表结构的 Default 列就会展示对应的预设数值。

这里我们补充一下 :默认值可以和可空、非空约束组合使用,像上面的 age、gender 字段本身允许为空,搭配默认值后,不传参就自动填充预设值;而带 not null 且无 default 的 name 字段,插入时必须手动填写有效值,无法依靠系统自动补值。

继续:

我们继续在 t13 表中插入数据,验证 default 默认值的执行规则。第一条插入语句完整填写三个字段 ('张三',19,'女'),用户手动传入了 age 和 gender 的具体数值,数据库优先使用我们填写的数据,最终存入 19、女,默认值不会生效。第二条插入只填写 name='李四',省略 age、gender 两个字段的赋值,因为这两个字段提前配置了 default 默认值,数据库自动补全预设内容,age 填充 18、gender 填充男。所以我们能总结默认值约束的核心规则:字段配置 default 时,插入数据手动传值就用用户数据,不传值则自动填充默认值。

那我们如果既指定 not null 又指定 Default 呢? 可以吗? 二者矛盾吗? :

下面我们继续新建 t14 表来验证 not null 非空约束和 default 默认值能否搭配使用。建表结构里,name 字段只加 not null、无默认值;age 只配置 default 18、允许为空;gender 同时标注 not null default '男'。建表语句正常执行成功,说明 not null 与 default 可以一起写在同一个字段后,二者不存在冲突。从desc t14的表结构也能看出:gender 字段 Null 列为 NO、Default 列为男,两种约束同时生效,印证组合配置是合法语法。

然后我们再插入了两条语句,出现了报错,第一条 insert into t14 (name,age,gender) values (NULL,20,'男');,报错 name 不能为null。因为 name 带有 not null 非空约束,规则禁止写入 NULL 空值,手动填 NULL 直接触发非空拦截报错。第二条 insert into t14 (age,gender) values (20,'男');,插入语句直接忽略了name字段,既没有手动赋值,name 又没有配置 default 默认值,数据库在缺省字段时没有备用数据可以自动填充,而非空约束又要求该字段必须有有效值,因此抛出提示:字段没有默认值,无法完成插入

所以我们可以总结出下面 3 条结论:

  1. 单个字段可以同时设置 not null + default,插入省略字段时,default 填充的值刚好满足 not null 非空要求,数据正常入库;
  2. 只带 not null、没有 default 的字段,插入时必须手动传入有效值,既不能填 NULL,也不能直接省略字段不赋值,否则数据库报错拦截;
  3. 只带 default、不带 not null 的字段,不传参数自动填充默认值,也可以手动插入 NULL。

继续:

我们继续基于 t14 表做插入,gender 字段配置为 not null default '男' 。先传入 ('张三',20,'男'),手动指定性别值,数据正常插入,使用用户填写内容。第二条语句主动给 gender 传入NULL,立刻抛出cannot be null报错,原因是 not null 约束禁止存入空值,即便字段存在默认值,也不能手动填 NULL。第三条插入语句只填写 name 和 age、省略 gender 字段,此时触发 default 机制,数据库自动填充默认值男,查询结果里 gender 字段自动为男。从这三条 SQL 能直观看出,not null 和 default 二者不存在冲突,反而互相补充约束逻辑。

所以我们就可以梳理出两种约束搭配后的完整规则:如果字段同时设置 NOT NULL + DEFAULT,用户手动传入 NULL 是非法操作,会被非空约束直接拦截;若插入语句直接忽略该字段不赋值,数据库就启用预先设置的默认值填充,默认值刚好满足 not null 非空要求,顺利完成数据入库。反过来,只带 not null 却没有 default 的字段,既不能写入 NULL,也不能省略字段不传值。

我们还可以再验证一下: Default 的年龄

t14 的 age 字段仅配置 default 18、没有非空约束,我们通过三条插入语句验证规则:第一条手动填写 30,最终存入用户填写的 30;第二条主动给 age 传入 NULL,因为没有 not null 限制,NULL 可以正常入库;第三条插入时省略 age 字段,数据库自动使用默认值 18 填充。查表结果和执行结果完全对应,也再次区分了只 default 与 not null+default 两种配置的行为差异,前者允许手动存 NULL,后者杜绝 NULL、缺省则走默认值。

继续:

我们继续新建表 t15 数,name 与 age 字段只定义了数据类型,既没有添加 not null 非空约束,也没有手动指定 default 默认值。执行 desc t15 查看表结构可以发现,两个字段的 Null 列都是 YES,Default 列统一标注 NULL。通过 show create table t15\G 查看原始建表语句能够找到关键原因:MySQL 对未添加非空约束的字段做了底层优化,自动隐性附加 DEFAULT NULL,也就是允许为空、缺省时自动填充 NULL,这是 MySQL 字段的原生默认规则。

下面我们可以验证一下 :

我们进行数据插入,第一条插入完整填写两个字段 ('张三',18),用户传入有效值,数据直接原样存入表中,没有触发默认填充逻辑。第二条插入主动给 name 赋值 NULL,由于字段没有非空限制,配合系统自带的 DEFAULT NULL 配置,NULL 能够正常入库,语句执行成功。第三条插入只填写 age=18,省略 name 字段。很多人会疑惑该字段没有手动写 default 为什么不报错,本质就是 MySQL 自动添加了隐性的 DEFAULT NULL,缺省字段时数据库自动填充 NULL,因此 SQL 正常执行,不会出现缺值报错。

我们可以归纳这条隐性默认规则:在建表时字段不写 not null、不自定义 default,MySQL 会自动帮字段配置 DEFAULT NULL,缺省不传值就自动存 NULL;一旦字段添加了 NOT NULL 非空约束,这条系统自动优化就会失效,不再附带隐性默认值,缺省字段又没有手动 default 时,插入直接报错。


四、comment 列描述

接下来我们学习 comment 字段注释,它和非空、默认值这类硬性数据约束不一样,comment 不限制任何数据的插入规则,没有强制校验作用,仅作为字段的文字备注说明。它的作用是留存字段业务含义,方便后续开发人员、DBA 查看表结构时,快速读懂每个字段代表的业务意义,属于偏向文档记录的软性约束。

继续举例:

我们继续新建表 t16,在每个字段末尾追加 comment 描述内容:name字段搭配 not null 约束并备注 "这个是用户的用户名",age 配置 default 18 同时注释 "这个是用户的年龄",gender 设置default '男' 并标注 "这个是用户的性别"。执行 desc t16 查看表结构时能够发现,常规的字段类型、Null、Default 列正常展示,但 comment 注释内容不会在这条结果里显示,这也是它和常规约束直观的区别。

我们执行插入语句 insert into t16 values('张三',19,'女');,可以顺利写入自定义的数据。能够看出 comment 完全不会限制用户传入的值,不管字段填什么内容,注释都不会对数据做拦截、校验,再次印证它只做备注、不约束数据的特性。

那如果想要查看提前编写的 comment 内容呢?

想要查看提前编写的 comment 内容,需要使用 show create table 表名\G 指令,在完整建表源码中,每个字段后方会完整带出我们预先写好的注释文字,这是查看字段备注的标准写法。

最后再补充一下:同一个字段一般不会同时搭配 not null 和 default,因为配置了 default 默认值后,缺省插入会自动填充有效值,天然满足非空的要求,额外添加 not null 属于多余配置,日常设计表结构时可以精简写法。

五、zerofill 零填充约束

接下来我们学习zerofill 零填充约束:

举例:

我们接着创建表 t17,两个字段均为 int unsigned not null,没有手动标注括号里的数字,在建表完成后通过 desc 和 show create table 查看表结构,能看到 MySQL 自动优化为 int(10)。这里为什么自动加 () 了,并且里面还是 10?

那这个10到底是什么?

我们继续向 t17 插入数据 (1,2),查询结果里 a 和 b 直接原样展示 1、2。在没有 zerofill 修饰的前提下,int (10) 的显示宽度不会对数据产生影响,数据库照常存原始数值。

下面我们修改一下,给字段追加 zerofill 约束,观察格式的变化:

我们执行 alter table t17 modify b int unsigned zerofill not null,为 b 字段新增 zerofill 零填充属性,查看表结构后,Extra 列无额外标识,但字段已经绑定零填充规则。

再次查询整张表,a 字段依旧显示 1,而原本数值为 2 的 b 字段变成 0000000002,一共 10 位字符,不足 10 位的部分在数字左侧自动补 0 补齐宽度。

我们继续添加数据,直观验证一下 zerofill 的展示规则:

我们继续向表 t17 中插入一条数据 (100,200),查询数据表后可以看到,普通字段 a 原样展示100,携带 zerofill 的 b 字段展示为 0000000200。设定显示宽度是 10 位,200 本身只有 3 位,因此在数字左侧自动补齐 7 个 0 凑满 10 位。这里关键要记住:zerofill 只改变查询展示效果,不会修改磁盘里实际存储的数字,数据库底层保存的数据依旧是 200。

为了证明实际存储没有补 0,我们执行 select a,hex(b) from t17。数值 2 对应的十六进制是 2、数值 200 对应的十六进制是 C8,和十进制换算完全匹配。十六进制取值直接读取字段原生存储内容,结果里没有多余的零,彻底说明前置补零只是客户端展示美化,真实数据没有发生变化。

我们先把 b 字段修改为 int(1) unsigned zerofill,显示宽度设定成 1。原有数据 2、200 的位数都大于等于 1,不再需要补零,查询时直接原样输出 2 和 200。紧接着再次修改字段为 int(4) unsigned zerofill,显示宽度调整为 4,数字 2 不足 4 位变成 0002,200 不足 4 位变成0200,位数超过设定宽度时依旧完整展示原数字。

我们再继续插入几组数据:

当前 b 字段限定为 int(4) unsigned zerofill,我们连续插入 b 字段值 1、11、111、1111、11111、111111 多条记录。查询结果可以直观看到:数值位数不足 4 位时,左侧自动补 0 补齐 4 位,比如 1 变成 0001、11 变成 0011、111 变成 0111;当数字位数等于或超过 4 位,例如 1111、11111、111111,不再补充前置 0,原样展示原始数字。由此可以总结 zerofill 的填充逻辑:它只是客户端展示层面的补充规则,数字长度达不到设定显示宽度就补零,超出宽度则保留原数据,不会截断原有数值。

还有个细节 : 为什么最开始检建表时的数字默认是10? 而不是其他数字?

我们继续通过 alter 语句去掉 a、b 字段的 zerofill 属性,再使用 show create table t17\G 查看建表语句,就会发现不带 unsigned 的普通 int 默认是int(11) ,添加 unsigned 无符号修饰的 int 默认是int(10)。这是为什么呢?

因为从存储空间原理来讲,int 固定占用 4 字节,有符号 int 取值上限是 2 的 31 次方,换算十进制最大为 2147483647,总共 10 位有效数字,因此无符号 unsigned 默认显示宽度 10;而有符号 int 还要额外占用 1 位表示符号位,取值下限是负数,最长数字连同负号合计 11 位,所以普通 int 默认显示宽度 11,这就是 MySQL 在建表时自动填充宽度数值的底层原因。

此时我们就可以总结一下 : int (M) 括号里的 M 是显示宽度,和 int 本身能存储的数值范围无关;只是代表显示宽度,单独写 int 类型时这个宽度不会生效,只有搭配 zerofill 才会体现作用 :数据位数<M,左边自动补 0 凑齐 M 位;数据位数 ≥ M,直接原样输出原值;补零仅作用于查询结果,物理存储始终是原始数字。

六、primary key 主键约束

接下来我们学习 primary key 主键约束:

主键是数据表里用来唯一标识单条记录的核心约束,它具备两大硬性规则:

  1. 字段数据不允许重复、不允许存入 NULL 空值
  2. 同时一张数据表最多只能设置一个主键字段

在实际业务设计中,我们需要依靠主键区分每一行数据,因此绝大多数业务表都会设计主键,主键字段也普遍选用整型编号,比如学号、用户 ID 这类唯一性的数据。

举例:

我们继续创建表 test_key,将 id int unsigned 字段后添加 primary key 设为主键,name 字段添加非空约束。执行 desc test_key 查看表结构可以发现,主键字段的 Null 列自动变成 NO,Key 列标注 PRI,这个标识就代表当前字段是主键。由此能看出 : 主键自带非空约束,添加数据时默认不能添加空数据,因此在建表时也不用额外添加 not null。

下面我们插入数据:

我们首先插入第一条数据 (1,'张飞'),数据正常插入。再次尝试插入 (1,'刘备'),因为主键 id=1 已经存在,出现主键重复报错,无法写入;更换 id 为 2 之后,(2,'刘备') 顺利插入。这组 SQL 直观体现主键唯一性:主键值全表唯一,重复数值会被数据库直接拦截,保证每条记录依靠 id 就能区分

主键除了约束数据格式,还能依托索引实现高效的数据操作。我们用 where id=2 条件查询,能够精准定位到刘备这条数据;之后执行 update 语句,依靠主键 id=2 修改姓名为曹老板,精准完成单条数据更新。日常开发中,我们普遍凭借主键完成单条数据的增删改查,依托主键索引提升 SQL 查询效率。
那如何去掉主键呢?

我们先执行 alter table test_key drop primary key; 删除表中原有的主键约束,执行完通过 desc test_key 查看表结构,id 字段的 Key 列原本的 PRI 标识消失,但之前主键自带的 NOT NULL 属性会保留。主键移除之后唯一性约束随之失效,此时再插入一条 (2,'孙权'),即便数据表已经存在 id=2 的数据,语句也能正常入库,表内出现两条 id 同为 2 的记录,直观说明主键消失后,重复数据不再被拦截。

那如果我们要再添加主键时呢?

在表中已经存在重复 id=2 的数据前提下,执行 alter table test_key add primary key(id); 试图重新给 id 追加主键,数据库直接报主键重复错误。这是主键的底层规则:给已有数据的字段添加主键时,数据库会全表校验数据,一旦字段内出现重复值,无法建立主键索引,添加操作直接失败。从这个现象可以总结开发规范:尽量在建表初期就定义好主键,避免大批量插入数据后再回头补主键,重复数据会阻碍主键创建。

上面我们是建表时添加的主键,那现在我们在建表后添加主键:

想要顺利重建主键,必须先清理冲突数据,这里执行 delete from test_key where name='孙权'; 删掉 id 重复的这条记录,表中 id 字段全部变成唯一值。再次执行添加主键语句 alter table test_key add primary key(id);,语句执行成功,desc 查看表结构,id 的 Key 列重新变回 PRI。此时再尝试插入(2,'孙权'),主键唯一性约束重新生效,重复 id 直接报错拦截。

最后使用 show create table test_key\G 查看完整建表源码,在建表语句末尾可以看到PRIMARY KEY (id),从建表定义层面确认 id 字段已经成功恢复为主键,完整闭环验证了主键删除、事后添加的整套约束逻辑。

复合主键

一张表中最多只能有一个主键,但是并不意味一个表中的主键只能添加给一列,也就是说一个主键可以被添加到两列或者多列,添加到多列中时就称为复合主键。复合主键的唯一性规则不再约束单个字段,而是多个字段组合起来整体不能重复。

举例 : 选课表就是典型业务场景:同一个学生可以选多门课、同一门课能被多名学生选择,但同一个学生不能重复选修同一门课程 ,因此我们恰好可以**用学生 id + 课程 id 做成复合主键。**如下:

我们新建一个选课的表 pick_course,把 id 学生编号、course_id 课程编号写在同一个 primary key 括号中,组成复合主键,剩余 score 字段用来存储分数。执行 desc 查看表结构后可以看到,id 与 course_id 两个字段的 Key 列都标注 PRI,并且两个字段自动附带非空约束,这是复合主键的结构特征

下面插入数据:

第一组插入 (1234,40,90);第二组插入 (1235,40,85),学生 id 不同、课程 id 相同,组合不重复,可以正常插入;第三组 (1234,41,90),学生 id 相同、课程 id 不一样,组合依旧唯一,同样插入成功。从三条数据能够看出:复合主键允许其中某一列单独重复,只要两列不同时重复就符合约束。

最后尝试再次插入 (1234,40,90),学生 id 和课程 id 和已有记录完全重合,字段组合出现重复,数据库抛出主键重复报错。由此总结复合主键核心:把参与主键的所有字段当成一个整体,字段组合唯一是硬性要求,单个字段各自可以重复,但是字段不能同时重复,这也是复合主键和单列主键最核心的区别。

七、总结

本文详细介绍了MySQL中常用的表级约束及其应用场景。主要内容包括:1. 非空约束(NOT NULL)的作用及与NULL值的区别,强调关键业务字段应设为非空以避免运算异常;2. 默认值约束(DEFAULT)的使用方法,说明其与NOT NULL约束的配合规则;3. 字段注释(COMMENT)的文档说明作用;4. 零填充约束(ZEROFILL)的显示格式化特性;5. 主键约束(PRIMARY KEY)的唯一性和非空特性,以及复合主键的组合唯一规则。通过具体建表示例和SQL操作演示,系统讲解了各类约束的语法、行为差异和实际应用,强调了约束在保障数据完整性和业务规范性方面的重要作用。

谢谢大家的观看!

相关推荐
拾贰_C2 小时前
【python | installation 】python 安装 | Windows | 命令使用
linux·数据库·ubuntu
贺今宵2 小时前
Vue 3 + Capacitor 使用jeep-sqlite,web端使用本地sqlite数据库
前端·数据库·vue.js·sqlite·web
列星随旋2 小时前
MySQL面经整理
数据库·mysql
AllData公司负责人2 小时前
大模型赋能AllData数据中台,系列升级|通过联合智谱大模型与Chat2DB开源项目,建设Text2SQL生产场景全新体验的数据源平台!
数据库·人工智能·text2sql·数据中台·数据源·chat2db·智谱大模型
是一个Bug2 小时前
MySQL 核心知识梳理:从底层原理到实战优化
mysql
minji...3 小时前
MySQL数据库 (四) MySQL的数据类型,tinyint,float,decimal,枚举enum和集合set
数据库·mysql·tinyint·enum·decimal·varchar·bit
阿演3 小时前
DataDjinn 新版本更新:国产数据库支持、连接树体验、AI 查询和表格编辑继续增强
数据库·人工智能·ai·ai编程
一只fish3 小时前
Oracle官方文档翻译《Database Concepts 26ai》附录-术语表
数据库·oracle
一只fish4 小时前
Oracle官方文档翻译《Database Concepts 26ai》第23章-数据库开发者概念
数据库·oracle