SQL入门(3):定义约束/断言assertion/触发器trigger
本文介绍数据库的完整性
完整性控制程序: 指定规则,检查规则 (规则就是约束条件)
动态约束 intergrity constraint::=(O,P,A,R)
O : 数据集合, 约束的对象 ?: 列, 多列的元组集合
P: 谓词条件: 什么样的约束?
A: 触发条件: 什么时候检查?
R: 响应动作: 不满足怎么办?
按照约束对象分类:
(1)域完整性约束条件: 施加在某一列上, 比如sage<25 and sage<40
(2)关系完整性约束条件: 施加在表上, 涉及多列, 2<=hours/credit<=16
按照约束来源分类:
(1)结构约束: 主键约束, 外键约束,是否允许空值等 primary key, foreign key, not null
(2) 内容约束: 取值范围, check(sage<25 and sage<40)
按照约束状态分类:
(1) 静态约束: 要求DB在任何时候都要满足的约束
(2) 动态动态: DB改变状态时要满足的约束, 例如salary 只能加不能减, 不能由1000改为500.---> 触发器
SQL支持如下几种约束:
静态约束中的列完整性 与表完整性, 动态约束中的触发器
(一) 静态约束
实现: create table
(1) col_constr 列约束 (一种域约束类型, 对单一列的值进行约束)
not null 列值非空
primary key 主键
not null + unique 就是非空+唯一性 ,实际上就是一个主键
check (search_condition) 列值满足的条件,
references tablename(colname) , colname 是tablename 的主键
on delete[ cascade| set null], 则删除被引用表的某一列v值时, 要将本表该列
值为v 的记录删除 或者 列值更新为null, 缺省为无操作.
例: 创建一个表 student
- create table student (sno char(8) not null unique, sname char(10),
- --not null unique 表示主键
- ssex char(2) constraint ctssex check(ssex='男' or ssex='女'),
- -- ctssex 是约束constraint 的名字. 之后可以单独处理
- sage integer check(sage>=1 and sage<150), -- 没有定义约束名, 则之后不能单独处理
- dno char(2) references dept(dno) on delete cascade, -- dno 在dept表中 是主键,
- sclass char(6));
on delete cascade 表示如果dept表中的某个'01'系被删除了,
那么在student 表中该系所有学生的dept 值为null, 如果没有加这个, 那么dept表中的删除操作对
student表没有影响.
- create table course (cno char(3), cname char(10), chours integer,
- credit float(1) constraint ctcredit check(credit>=1.0 and credit <=6.0),
- tno char(3) references teacher(tno) on delete cascade);
- -- 或者通过alter
- alter table course add constraint
- cs_tno foreign key(tno) references teacher(tno) on delete cascade;
- -- 移除约束
- alter table course drop constraint cs_tno;
补充: unique 和not null
- create table tbl1(name1 varchar(10), num1 varchar(10),
- constraint cs_num1 unique(num1));
- -- 或者
- create table tbl1(name1 varchar(10), num1 varchar(10) unique);
- -- 之后再添
- alter table tbl1 add constraint cs_num1 unique(num1);
- alter table tbl1 drop constraint ;
- -- 非空约束
- create table tbl1(name1 varchar(10), num1 varchar(10) not null);
- -- 新增非空约束
- alter table tbl1 modify num1 not null;
- -- 删除非空约束 不是用drop
- alter table tbl1 modify num1 null;
(2) table_constr 表约束, 用于多列或者元组的值进行约束
- create table student ( sno char(5) not null unique,sname char(5),
- ssex char(2) constraint ctssex check(ssex='男' or ssex='女') ,
- sage integer check(sage>1 and sage<150).
- dno char(3) references dept (dno) on delete cascade,
- sclass char(5),primary key(sno));
--primary key(sno) 可以放在sno 这一列的后面, 也可以放在最后这里, 看成是表约束
- create table course (cno char(3), cname char(10), chours integer,
- credit float(1) constraint ctcredit check(credit>=1.0 and credit <=6.0),
- tno char(3) references teacher(tno) on delete cascade,
- primary key (cno), constraint ctcc check(chours/credit=));
- -- 严格约束12课时对应1个学分
- create table sc(sno char(5), cno char(3),
- score float(1) constraint ctscore check(score>=0.0 and score<=100.0),
- foreign key(sno) references student(sno) on delete cascade,
- foreign key(cno) references course(cno) on delete cascade);
注意: check 后面的条件可以是select from where 语句
- create table sc(sno char(5) check (sno in (select sno from student)),
cno char(3), check(cno in (select cno from course)), --相当于外键- score float(1) constraint ctscore check(score>=0.0 and score<=100.0);
注意: create table 中的约束条件 可以在后面根据需要进行撤销 ,也可以追加约束
alter table tablename +
add 追加约束, 也可以增加新的一列
drop 删除一列的约束,或者删除一列,
modify 修改
- alter table sc drop constraint ctscore; -- 撤销对score的约束ctscore;
- alter table sc
- modify ( score float(1) constraint nctscore check(score>0.0 and score<=150.0));
-- 修改约束- alter table sc
- add ( score float(1) constraint nctscore check(score>0.0 and score<=150.0));
-- 增加约束
(3) 断言 assertion
一个断言就是一个谓词表达式, 它表达了希望数据库总能满足的条件, 表约束与 列约束就是一些特殊的断言.
还有复杂的断言 create assertion [assertion name] check [predicate]
那么之后数据库的每一次更新去判断是否违反该断言, 断言测试增加了数据库维护的负担, 没事不要使用!!
例如: 每位教师同一时间段不能在两个不同的地方上课.
实例1: 已知下列4张表
borrower(client_name,loan_num) 客户以及他的贷款
account(account_num,balance) 账户和余额
depositor(account_num, client_name) 账户与客户名
loan(loan_num, amount) 每一笔贷款
现在规定: 每一笔贷款 , 要求至少这个借款者的账户中有最低余额500元.
- create assertion balance_cst check
- (not exists (select * from loan
- where not exists (select * from borrower b, depositor d, account a
- where loan.loan_num=b.loan_num and
- b.client_name=d.client_name and
- a.account_num=d.account_num and a.balance>=500)));
实例2: 现有3张表
account(branch_name, account_num, balance) 分行 账户 与 余额
loan(branch_name,loan_num,amount) 分行的每一笔贷款
branch(branch_name,..) 分行信息
每一个分行的贷款总量要小于该分行所有账户的余额总额 (不存在某一个分行 它的贷款额大于余额)
- create assertion sum_cst check
- (not exists (select * from branch where (select sum(amount) from loan
- where loan.branch_name=branch.branch_name) >=
- (select sum(balance) from account where account.branch_name=branch.branch_name)));
(二) 动态约束
以上 create table 中的表约束与列约束 是静态约束, 下面介绍动态约束--> 触发器 trigger
动态约束是一种过程完整性的约束, 相比之下, 之前的create table 的约束是非过程性约束
动态约束是一个程序, 该程序可以在特定的时刻被自动触发执行: 比如在一次更新之前,
或者一次更新之后的执行.
动态约束 intergrity constraint::=(O,P,A,R), O P A R 都需要定义, 再来回顾下
O : 数据集合, 约束的对象 ?: 列, 多列的元组集合
P: 谓词条件: 什么样的约束?
A: 触发条件: 什么时候检查?
R: 响应动作: 不满足怎么办?
以下是Oracle 的触发器的语法例子, 在SQL server中 语法略有差别, 但是思路一致. ..
创建触发器的基本语法:
create trigger trigger_name
before| after [insert | delete|update] [of colname] on tablename
for each row| for each statement
when [search_condition]
[statement]
[begin atomic statement; ... end;] --多个条件
注意: row , as 可以省略!
实例(1): 当teacher表更新元组时, 控制其工资只能涨不能跌
- create trigger teacher_sal-- 触发器名字
- before update of salary on teacher -- 作用在什么表的什么列
- referencing new x, old y -- 定义更新前后的值
- for each row when(x.salary<y.salary) -- 对每一条记录都要检查,
- begin --如果违反则执行
- raise_application_error(-20003,'invalid salary on update');
- -- Oracle的错误处理函数, 提示无效更新
- end;
实例(2) : student(sno, sname, sumcourse), sumcourse 表示该同学已经学习的课程门数,
初始值是0, 以后每修一门课都要对其+1, 设计一个触发器自动完成这个功能.
- create trigger sumc
- after insert on sc -- 对于sc 的新增信息 作出反应
- referencing new row newI-- 定义更新后的行=newi
- for each row
- begin -- 执行操作
- update student set sumsourse=sumcourse+1
- where sno=:newi.sno; -- 这条记录(行)对应的学号
- end;
实例(3) :student(sno, sname, sage,ssex,scalss) 中某一个学生变动其主码sno
,则在sc 表中该同学的学号也要相应改变
- create trigger upd_sno
- after update of sno on student --指明更新的地方
- referencing old oldi, new newi
- for each row
- begin
- update sc set sno=newi.sno where sno=: oldi.sno;
- end;
实例(4) :student(sno, sname, sumcourse)中删除某一个学生sno时, 在sc 中该学生的
选课记录也要删除
- create trigger del_sno
- after delete on student
- referencing old oldi
- for each row
- begin
- delete sc where sno=:oldi.sno;
- end;
实例(5) : student(sno, sname, sumcourse)中删除某一个学生sno时, 在sc 中该学生的sno设置为null
- create trigger del_sno
- after delete on student
- referencing old oldi
- for each row
- begin
- update sc set sno=null where sno=:oldi.sno;
- end;
实例(6) :假设有两张表, dept(dno,dname,dean) ,该表字段是系号 系名 系主任名, 以及
teacher(tno,tname,dno,salary) . 现在需要控制 在对dept 的dean 做更新的时候,
必须满足dean 的工资是同一系里最高的, 否则更新报错.
- create trigger dean_sal
- before update of dean on dept -- 对dept 的dean 做更新的时候
- referencing old oldi , new newi -- 更新前后的新 旧定义
- for each row when(dean not in
- (select tname from teacher where dno=:newi.dno and salary> =
- all(select salary from teacher where dno=:newi.dno )))-- 同系教师工资
- begin -- 不满足条件时
- raise_application_error(-20003,'invalid dean on update');
- end;
SQL入门(3):定义约束/断言assertion/触发器trigger的更多相关文章
- zabbix入门之定义触发器
zabbix入门之定义触发器 触发器的概念 触发器的定义:界定某特定的item 采集到数据的非合理区间或非合理状态.通常为逻辑表达式. 逻辑表达式(阈值):通常用于定义数据的不合理区间,其结果如下: ...
- 详解如何定义SQL Server外关键字约束
SQL Server外关键字约束定义了表之间的关系.当一个表中的一个列或多个列的组合和其它表中的主关键字定义相同时,就可以将这些列或列的组合定义为外关键字,并设定它适合哪个表中哪些列相关联.这样,当在 ...
- SQL Server 数据库的维护(二)__触发器
--维护数据库-- --触发器-- --概述: 触发器是一种特殊类型的存储过程,用来强制执行业务规则.在调用执上,触发器不能像存储过程那样可以由用户通过T-SQL语句直接调用,而是需要有数据库所发生的 ...
- 第87节:Java中的Bootstrap基础与SQL入门
第87节:Java中的Bootstrap基础与SQL入门 前言复习 什么是JQ? : write less do more 写更少的代码,做更多的事 找出所有兄弟: $("div" ...
- Oracle PL/SQL入门之慨述
Oracle PL/SQL入门之慨述 一.PL/SQL出现的目的 结构化查询语言(Structured Query Language,简称SQL)是用来访问关系型数据库一种通用语言,它属于第四代语言( ...
- SQL从零到迅速精通【触发器】
essay from:http://www.cnblogs.com/hoojo/archive/2011/07/20/2111316.html 触发器就类似一个小账本,记录了你在数据库做了哪些操作,可 ...
- SQL入门经典(十) 之事务
事务是什么?事务关键在与其原子性.原子性概念是指可以把一些事情当作一个执行单元来看待.从数据库角度看待.他是指应该全部执行或者全部不执行一条或多条语句的最小组合.当处理数据时候经常确保一件事发生另一件 ...
- SQL入门经典(一)之简介
今天是我第一天开通博客,也是我的第一篇博客.以后为大家带来第一篇关于学习技术性文章,这段时间会为大家带来是SQL入门学习.希望大家坚持读下去,因为学历有限.我也是初学者.语言表达能力不好和知识点不足, ...
- SQL Server缺省约束、列约束和表约束
SQL Server缺省约束是SQL Server数据库中的一种约束,下面就为您介绍SQL Server缺省约束.列约束和表约束的定义方法啊,供您参考. SQL Server缺省约束 SQL Serv ...
随机推荐
- 第四章· Redis的事务、锁及管理命令
一.事务介绍 二.Redis乐观锁介绍 三.Redis管理命令 一.事务介绍 Redis的事务与关系型数据库中的事务区别 1)在MySQL中讲过的事务,具有A.C.I.D四个特性 Atomic(原子性 ...
- c语言提高篇 第一天
一.听课标准 1.选择法排序 2.会简单封装函数 3.数组做函数参数会退化为一级指针 a.数组做函数参数时,应该吧数组元素个数也传递给函数 b.形参中的数组,编译器把它仿作指针处理,c语言特色 c.实 ...
- Python——模块——随机模块
1.引用模块 import random 2.随机整数 random.randint(a,b) 3.随机浮点数 random.uniform(a,b) 4.从列表中随机取元素 random.choic ...
- [转载:Q1mi]Bootstrap和基于Bootstrap的登录验证示例
转载自:Q1mi Bootstrap介绍 Bootstrap是Twitter开源的基于HTML.CSS.JavaScript的前端框架. 它是为实现快速开发Web应用程序而设计的一套前端工具包. 它支 ...
- 2.2 collection 模块
2.2.1 定义命名元祖 2.2.2 定义双端队列 2.2.3 定义有序的字典 2.2.4 定义有默认值的字典
- Matlab中simulink的state space模块
%列写状态空间表达式矩阵 A=[- -;]; B=[ ; ]; C=[ ; ]; D=[ ; ]; %得到传递函数表达式 [num, den]=ss2tf(A, B, C, D, ); %在命令行打印 ...
- pta寒假作业3
题目三:捉老鼠啊,亏了还是赚了 实验代码 #include <stdio.h> #include <stdlib.h> int main(void) { ...
- Luogu P1654 OSU!
写法和CF235B Let's Play Osu!非常相似.但是这个题厉害就厉害在统计的贡献里面有一个平方的期望,而这个平方的期望和期望的平方是完全不一样的,需要另外统计,逻辑上仔细想一想就会明白. ...
- lcd驱动框架
目录 lcd驱动框架 框图 程序分析 入口 打开open 读read 初始化registered_fb 注册 小结 程序设计 测试 方式一操作fb0 方式二操作tty 方式三操作终端 完整程序 tit ...
- Linux测试硬盘读性能的常用工具-hdparm和dd俩搭档
Linux测试硬盘读性能的常用工具-hdparm和dd俩搭档 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.hparm # 它用来在基于 Linux的系统上获取或 ...