oracle数据库:约束

article/2025/9/28 4:40:51

约束简介

约束是数据库用来确保数据满足业务规则的手段,不过在真正的企业开发中,除了主键约束这类具有强需求的约束,像外键约束,检查约束更多时候仅仅出现在数据库设计阶段,真实环境却很少应用,更多是放到程序逻辑中去进行处理。这也比较容易理解,约束会一定程度上较低数据库性能,有些规则直接在程序逻辑中处理就可以了,同时,也有可能在面对业务变更或是系统扩展时,数据库约束会使得处理不够方便。不过在我看来,数据库约束是保证数据准确性的最后一道防线,对于设计合理的系统,处于性能考虑数据库约束自然可有可无;不过若是面对关联关系较为复杂的系统,且对系统而言,数据的准确性完整性要高于性能要求,那么这些约束还是有必要的,否则,就会出现各种相对业务规则来说莫名其妙的脏数据。总之,对于约束的选择无所谓合不合理,需要根据业务系统对于准确性和性能要求的侧重度来决定。

oracle数据库的约束有五种:

  • 主键约束(primary key
  • 唯一约束(unique
  • 非空约束(not null
  • 外键约束(foreign key
  • 检查约束(check

1,主键约束 primary key

主键是定位表中单个行的方式,可唯一确定表中的某一行,关系型数据库要求所有表都应该有主键,不过oracle数据库没有遵循这个规范,oracle中的表可以没有主键(这种情况不多见),关于主键有几个需要注意的点:

  1. 键列必须具有唯一性,且不能为空,其实主键约束相当于unique+not null
  2. 一个表中只允许有一个主键
  3. 主键所在列必须具有索引(主键的唯一约束通过索引来实现),如果不存在,将会在索引添加的时候自动创建。

2,唯一约束 unique

唯一约束可作用在单列或者多列上,对于这些列或者列组合,唯一性约束保证每一行的唯一性。
唯一性约束有以下几个注意点:

  • 对于unique来说,所以是必须的。如果不存在,就自动创建一个(unique的唯一性本质上是通过索引来保证的)
  • unique允许存在null值,unique约束的列可以存在多个null,这是因为,unique唯一性通过btree索引来实现,而btree索引中不包含null。当然,这也造成了在where语句中使用null值进行过滤会造成全表扫描。

3,非空约束 not null

非空约束作用的列也叫强制列。顾名思义,非空列中必须要有值,当然建表的时候如果使用default关键字指定了默认值,则可以不输入。

4,外键约束 foreign key

外键约束定义在具有父子关系的子表中,外键约束使得子表中的列对应父表的主键列,用以维持数据库的完整性。不过出于性能和后期的业务系统扩展的考虑,很多时候,外键约束仅仅出现在数据库的设计中,实际会放在业务程序中进行处理。外键约束要注意以下几点:

  1. 外键约束的子表中的列和对应父表中的列数据类型必须相同,列名可以不同
  2. 对应的父表列必须存在主键约束(primary key)或者唯一约束(unique
  3. 外键约束允许列存在null值,对应的行就成了孤行。

其实很多时候不使用外键,很多人认为会让删除操作变得比较麻烦,比如要删除父表中的某条数据,但是某个子表中又有对该条数据的引用,这时就会导致删除失败。这种情况下有几种方式来优化这个场景:

  1. 第一种方式简单粗暴,删除的时候,级联删除掉子表中的所有匹配行,在创建的时候,通过on delete cascade 子句指定该外键列可以级联删除。
  2. 第二种方式,删除父表中的对应行,会将对应子表中的所有匹配行的外键约束列置为null,通过on delete set null子句实现
  3. 第三种,默认,强制不让删

5,检查约束 check

检查约束可以用来实施一些简单的规则,比如列值必须在某个范围内,检查的规则必须是一个结果为truefalse的表达式。

6,创建表时创建约束

这里以创建下面两张比表为例子
表名:w_user 用户表

编号字段名字段类型说明
1useridnumber(5)用户id,主键约束
2usernamevarchaer2(30)用户名,非空约束,4~20个字符
3userpwdvarchar(20)密码,非空约束,4~18个字符
4agenumber(3)年龄,默认18,值大于等于18
5genderchar(2)性别,默认‘男’,只能是‘男’或者‘女’
6emailvarchar2(30)邮箱,唯一约束
7regtimedate注册日期,默认当前日期

表名:w_txt 文章表

编号字段名字段类型说明
1txtidnumber(5)文章编号,主键约束
2titlevarchar2(32)文章标题,非空约束,长度4~20字符
3txtvarchar2(1024)内容,最大长度1024
4pubtimedate发布日期,默认当前日期
5useridnumber(5)作者,外键约束,参考用户表的用户id,删除时,自设为null

创建w_user表:

--创建w_user表,同时加上约束,不设置约束名称
create table w_user(userid number(5) primary key,--主键,唯一且非空username varchar2(30) not null check(length(username ) between 4 and 20),--检查约束和非空约束userpwd varchar2(20) check(length(userpwd) between 4 and 18) not null,--检查约束和非空约束age number(3) default(18) check(age>=18),--设置默认值和检查约束gender char(4) default('男') check(gender in('男','女')),--默认值和检查约束email varchar2(30) unique,--唯一约束regtime date default(sysdate) --默认系统当前时间
);

执行之后找到创建好的表,打开查看结构【客户端用的PLSQL】:
在这里插入图片描述
点击检查可以查看设置的检查约束
在这里插入图片描述
接下来创建第二张表:

--创建w_txt表
create table w_txt(txtid number(5) primary key,title varchar2(32) not null check(length(title)>=4 and length(title)<=30),txt varchar2(1024),pubtime date default(sysdate),userid number(5) references w_user(userid) on delete set null
);

最后一个字段是外键,这里on delete set null 意思是当w_user表里面的某个userid删除之后,这个表里面对应的设置为null
在这里插入图片描述
打开表看一下结构如上图所示,这里主要看一下外键约束。

7,创建表时,创建带名字的约束

在创建上述两张表的时候并没有指定对应的约束名称,这样当我们后期对表进行一些操作的时候,如果违反了某个约束,报错的时候提示的是系统默认的约束名称,很不方便我们找到错误,因此可以直接给约束指定名称。

这里先把刚才的表删除,或者把下面创建的表的名字改一下

--删除表
drop table w_txt;
drop table w_user;

创建约束带有名字的w_user

--创建约束带有名字的w_user表
create table w_user(userid number(5),username varchar2(30) constraint nn_user_name not null,--检查约束和非空约束userpwd varchar2(20) constraint nn_user_pwd not null,--检查约束和非空约束age number(3) default(18),--设置默认值和检查约束gender char(4) default('男'),--默认值和检查约束email varchar2(30),--唯一约束regtime date default(sysdate),constraint pk_user_id primary key(userid),--给userid追加主键约束constraint ck_user_name check(length(username) between 4 and 20),--给username追加check约束constraint ck_user_pwd check(length(userpwd) between 4 and 18),--给userpwd追加check约束constraint ck_user_age  check(age>=18),--给age追加check约束constraint ck_user_gender  check(gender in('男','女')),--给gender追加check约束constraint ck_uaer_email unique(email)--给email追加唯一约束
);

创建约束带有名字的w_txt

--创建约束带有名字的w_txt表
create table w_txt(txtid number(5),title varchar2(32) constraint nn_txt_title not null,txt varchar2(1024),pubtime date default(sysdate),userid number(5),constraint pk_txt_id primary key(txtid),constraint ck_txt_title check(length(title)>=4 and length(title)<=30),constraint fk_txt_user_id foreign key (userid) references w_user(userid)  on delete set null
);

创建之后查询能看到跟刚才一样,并且这是大部分约束都起了名字,default一般不用起名字。
在这里插入图片描述

8,创建表之后追加约束

有时候我们创建表的时候没考虑太多,创建好之后才发现某些字段需要加上约束,这时候可以使用追加约束的sql语句实现功能。
还是接上面的表,先把之前的表删除(因为创建的表内容都一样),也可以给接下来创建的表改个名字,创建时不报错就行。

--删除表
drop table w_txt;
drop table w_user;

创建w_user表:

--创建w_user表 不带约束
create table w_user(userid number(5),username varchar2(30),userpwd varchar2(20),age number(3),gender char(4),email varchar2(30),regtime date
);

创建的这个表一个约束都没有,看一下表的结构:
在这里插入图片描述
其中键和检查这两页都是空白【这里就不截图了】,接下来给这个表添加之前的那些约束:

--给表添加约束
--userid追加主键
alter table w_user add constraint pk_user_id primary key(userid);
--username追加非空和check约束
alter table w_user modify(username constraint nn_user_name not null);--非空约束
alter table w_user add constraint ck_user_name check(length(username) between 4 and 20);--检查约束
--userpwd追加非空约束和check约束
alter table w_user modify(userpwd constraint nn_user_pwd not null);--非空约束
alter table w_user add constraint ck_user_pwd check(length(userpwd) between 4 and 18);--检查约束
--age追加check约束和默认值
alter table w_user add constraint ck_user_age  check(age>=18);--check约束
alter table w_user modify(age default(18));--追加默认约束
--gender追加check和default
alter table w_user add check(gender in('男','女'));--check约束
alter table w_user modify(gender default('男'));--追加默认约束
--email追加唯一约束
alter table w_user add constraint uq_uaer_email unique(email);--唯一约束
--regtime追加默认值
alter table w_user modify(regtime default(sysdate));--追加默认约束

执行之后查看表的结构:
在这里插入图片描述
再看一下检查界面
在这里插入图片描述
接下来给w_txt创建没有约束的表,以及追加约束:

--创建w_txt表,不添加约束
create table w_txt(txtid number(5),title varchar2(32),txt varchar2(1024),pubtime date,userid number(5)
);

同上w_user表,现在没有添加任何的约束,接下来给表中追加约束:

--创建w_txt表,不添加约束
create table w_txt(txtid number(5),title varchar2(32),txt varchar2(1024),pubtime date,userid number(5)
);--给w_txt追加约束
--txtid添加主键约束
alter table w_txt add constraint pk_txt_id primary key(txtid);--主键约束
--title添加非空约束以及check约束
alter table w_txt modify(title constraint nn_txt_title not null);--非空约束
alter table w_txt add constraint ck_txt_title check(length(title)>=4 and length(title)<=30);--检查约束
--pubtime设置默认值
alter table w_txt modify(pubtime default(sysdate));--追加默认约束
--userui设置外键约束
--方法1:强制不让删 【文章表的内容没删除干净之前,用户表的内容不让删】
alter table w_txt add constraint fk_txt_user_id foreign key (userid) references w_user(userid);--强制不让删
--方法2:自动设置为null 【如果文章没有删除,然后用户id删除了,那么文章的关联id自动设置为null】
alter table w_txt add constraint fk_txt_user_id foreign key (userid) references w_user(userid) on delete set null;--自动设置为null
--方法3:级联删除 【当用户表的id删除时,文章表对应的内容一起删除】
alter table w_txt add constraint fk_txt_user_id foreign key (userid) references w_user(userid) on delete cascade;--级联删除

添加外键有三种方式,之前设置的是自动设置为空,这里运行的是设置为空,三种方法是选一种运行,同时运行多个会报错的。看一下表的结构:
在这里插入图片描述
看一下检查界面:
在这里插入图片描述
看一下键界面:
在这里插入图片描述

9,禁用和启用约束

很多时候由于业务需要,比如我们有大量的历史数据,需要和现有数据合并,当前表存在数据库约束(如非空约束),而这些历史数据又包含违背非空约束的数据行,为了避免导入时由于违反约束而导入失败,我们通过调整约束状态来达到目的。

数据库约束有两类状态

  • 启用/禁用(enable/disable):是否对新变更的数据启用约束验证
  • 验证/非验证(validate/novalidate):是否对表中已客观存在的数据进行约束验证

这两类四种状态从语法角度讲可以随意组合,默认是enable validate
下面我们来看着四类组合会分别出现什么样的效果:

  • enable validate:默认的约束组合状态,无法添加违反约束的数据行,数据表中也不能存在违反约束的数据行;
  • enable novalidate:无法添加违反约束的数据行,但对已存在的违反约束的数据行不做验证;
  • disable validate:可以添加违反约束的数据行,但对已存在的违反约束的数据行会做约束验证(从描述中可以看出来,这本来就是一种相互矛盾的约束组合,只不过是语法上支持这种组合罢了,造成的结果就是会导致DML失败)
  • disable novalidate:可以添加违法约束的数据行,对已存在的违反约束的数据行也不做验证。

拿上面的例子来说,我们需要上传大量违反非空约束的历史数据(从业务角度讲这些数据不会造成系统功能异常),可以临时将约束状态转为disable novalidate,以保证这些不合要求的数据导入表中。

举个例子:

alter table w_user add primary key(userid) disable;--禁用主键
alter table w_user modify primary key(userid) enable novalidate;--启用主键并验证

10,删除约束

语法:

alter table 表名 drop constraint 约束名 cascade

从上面的语法结构中可知,要删除约束就要知道对应约束的名称,所以给约束起名字是一个很好的习惯。

alter table w_user drop constraint uq_user_email cascade

这个sql语句最后的cascade是级联删除,意思是把跟这个约束相关的约束一起删除。


http://chatgpt.dhexx.cn/article/wo454V1w.shtml

相关文章

[数据库]表的约束

●&#x1f9d1;个人主页:你帅你先说. ●&#x1f4c3;欢迎点赞&#x1f44d;关注&#x1f4a1;收藏&#x1f496; ●&#x1f4d6;既选择了远方&#xff0c;便只顾风雨兼程。 ●&#x1f91f;欢迎大家有问题随时私信我&#xff01; ●&#x1f9d0;版权&#xff1a;本文由[你帅…

MySQL数据库,数据的约束

目录 1.数据的约束 1.1约束的类型 1.2NULL约束 1.3UNIQUE约束 1.4DEFAULT约束 1.5PRIMARY KEY约束 1.6FOREIGN KEY约束 1.数据的约束 首先&#xff0c;创建一个名为test的数据库&#xff1a; mysql> create database test charset utf8; Query OK, 1 row affected …

MySQL数据库(数据库约束)

目录 数据库约束 数据库约束的类型&#xff1a; null约束 &#xff1a; unique约束&#xff08;唯一约束&#xff09;&#xff1a; default约束&#xff08;默认值约束&#xff09;&#xff1a; primary key约束&#xff08;主键约束&#xff09;&#xff1a; for…

数据库中的8种常见约束定义

数据库中常见约束的定义理解和应用&#xff08;附代码&#xff09; 首先来说数据库中约束的定义是什么&#xff1f; 约束定义&#xff1a;按照表中的数据规则&#xff0c;如果存在违反约束的数据行为&#xff0c;行为就会被阻止。 一般在创建表之后就会创建相关列的约束&#…

基础SQL第二课:约束

一、约束&#xff1a; 什么是约束&#xff1f; 为了确保表中的数据的完整性(准确性、正确性)&#xff0c;为表添加一些限制。是数据库中表设计的一个最基本规则。使用约束可以使数据更加准确&#xff0c;从而减少冗余数据&#xff08;脏数据&#xff09;。 数据库完整性约束分…

sublime解决中文乱码问题

首先找到你选择的build-system&#xff0c;如下图所示&#xff1a; 第二步&#xff1a;找到preferences下的browse packages&#xff0c;点击进入目录 第三步&#xff1a;找到对应的.sublime-build文件 第四步&#xff1a;打开文件&#xff0c;将"env": {"LANG&…

sublime text 3211 安装中文包

sublime text 3211 安装中文包 安装步骤&#xff1a; 1、打开Sublime Text3&#xff0c;选择Preferences ->Package Contorol 2、在Sublime Text3 弹窗输入install package&#xff0c;选择对应命令,然后鼠标点击安装install package 3、等待一会Sublime Text3 的 insta…

Sublime 中文命名乱码(显示为方框)

今天在使用Sublime中发现&#xff0c;将文件名以部分文字以中文命名&#xff0c;非中文部分能正常显示&#xff0c;中文部分显示不出来。如下图所示 这里就是python能显示出来&#xff0c;其他的汉字就变成了方框。与此对应的现象还有部分文本的部分内容显示为繁体 &#xff0…

解决sublime汉化后部分中文显示为繁体字

解决sublime汉化后部分中文显示为繁体字 1. 问题描述2. 解决方法3. 修正之后的效果 1. 问题描述 使用插件下载汉化包之后&#xff0c;部门字体仍显示为繁体&#xff0c;如下图 这种字体看着实在是别扭的不行 2. 解决方法 找到首选项 -> 设置 添加以下内容 "font_o…

关于sublime中文上下跳动错位的解决方法

关于sublime中文上下跳动错位的解决方法 在preferences-settings打开 增加"font_options":[“gdi”] 对比效果如下&#xff1a;

Sublime text文本编辑器中文乱码解决方法

Sublime text 出现中文乱码的解决方法 问题描述 Sublime text文本编辑器用起来感觉挺好的&#xff0c;它的代码补全功能非常不错&#xff0c;界面也很漂亮。 最近在学习C语言&#xff0c;我感觉Dev-C的界面比较朴实&#xff0c;代码补全功能操作性太强。因此&#xff0c;我会…

Sublime Text3 中文错位解决办法

在使用prettytable库打印列表时偶然发现&#xff0c;相同的中英文混合字符串表格在Windoows控制台以及NotePad上能对齐显示&#xff0c;在SublimeText3以及EmEditor上无法对齐显示&#xff1a; Windoows控制台&#xff08;能对齐显示&#xff09;&#xff1a; EmEditor&…

sublime离线插件安装

一、首先需要安装Package Control 参考官网&#xff1a;Installation - Package Control中的方法。 其中分联网自动下载安装和手动两种。本文介绍手动的。 Click the Preferences > Browse Packages… menuBrowse up a folder and then into the Installed Packages/ fold…

解决 Sublime Text 中文样式显示异常问题

目录 一、问题背景 二、问题解决 1&#xff09;在工具栏中选择 Preferences → Settings &#xff0c;打开配置文件 2&#xff09;在右侧界面添加下方代码块中的内容&#xff0c; CtrlS 保存 三、效果展示 一、问题背景 最近在单位的Mac系统中使用Sublime Text感觉良好&a…

sublime text里面中文字体显示异常解决方案

sublime text下载之后一开始转成中文之后&#xff0c;会出现中文显示异常的问题&#xff0c;比如下图中“门”字显示异常 通过如下的设置可以解决该问题&#xff1a; 首选项--》设置 在该位置添加如下内容&#xff1a; {"font_options": ["gdi"],"dp…

Linux sublime设置中文,Sublime Text 3 设置为Ubuntu 14.04默认编辑器并支持中文

Ubuntu 14.04下设置Sublime Text 3支持中文输入 发现Sublime Text不支持中文&#xff0c;我用的是Fctix&#xff0c;查了好长时间教程搞定了&#xff0c;在此分享并记录下&#xff0c;最后附上本次所需文件的下载地址。 1、 复制如下的代码为sublime_imfix.c文件并放到sublime_…

sublime匹配汉字

需要处理的文本 GET/aaa/v1/xxx【门户】获取商机列表信息 POST/aaa/v1/xxx创建商机接口 POST/aaa/v1/xxx/approve审核渠道报备商机 GET/aaa/v1/xxx/areaSales根据区域编码获取对应的销售负责人(渠道经理) POST/aaa/v1/xxx/assign分派渠道报备商机 POST/aaa/v1/xxx/convert/ord…

解决SublimeText中文注释乱码

在使用Sublime Text过程中&#xff0c;出现文件中中文呈现乱码的情况 解决&#xff1a;安装Package Control --> 安装插件ConvertToUTF8 1. 安装Package Control 1&#xff09;Preferences --> Browse Packages&#xff0c;进入打开上层目录&#xff0c;选择Installed…

Sublime 打开文件中文乱码

解决步骤&#xff1a; 1. Ctrl Shift P 打开命令行 2. 输入install Package Control &#xff0c;点击进行安装 3. CTRLSHIFTP > 安装 Install Package 4. Install Package 安装完毕后&#xff0c;在弹出的命令行&#xff0c;输入ConvertToUTF8&#xff0c;点击进行安装…

Sublime中文乱码问题!今天星期四~

Sublime使用过程中&#xff0c;不知道为啥里面的中文注释全部变成了乱码&#xff01;&#xff01;&#xff01;好生气&#xff01; 问题描述 变成乱码之后我按照搜索的教程下载 Package Install&#xff0c;ConvertTOUTF-8&#xff0c;结果全都不行&#xff01;&#xff01; …