Sql-Server数据库完整性、存储过程 4.19数据库课程实验

SQL要结束了

1、数据库完整性

数据库完整性是指数据库中存储数据的正确性和相容性,符合现实世界的语义、反映当前的现实状况;数据的相容性是指数据库同意对象在不同关系表中的数据是符合逻辑的

1.1 实体完整性

实体完整性指表的主码不能为 null,主码需要在创建表时定义

create table Student
(
	Sno varchar(15) primary key, --列级定义主码
	Sname varchar(10),
	Ssex char(2),
	Sage smallint,
	Sdept varchar(10)
); --Sno为主码,即一个学号唯一对应一名学生

create table SC
(
	Sno varchar(15),
	Cno varchar(10),
	Grade smallint,
	primary key(Sno,Cno) --表级定义主码
); --多个属性为主码时,只能表级定义

1.2 参照完整性

参照完整性指表中的外码属性值或者为 null,或者为其被参照关系表中的某个元组的主码值

create table SC
(
	Sno varchar(15),
	Cno varchar(10),
	Grade smallint,
	primary key(Sno,Cno), --表级定义主码
	foreign key(Sno) references Student(Sno),
	foreign key(Cno) references Course(Cno) --定义参照关系
); --SC表的Sno属性值必选在Student表中存在,SC表的Cno属性值必选在Cource表中存在

参照关系相当于将多个表以该种方式联系在了一起,当删除元组时,有可能会违反参照完整性,如:删除了Student中的某个元组,但该元组的Sno属性值与SC表的某个元组的Sno属性值形成了对照,会拒绝执行

可指定在违反参照完整性时,系统执行的策略

create table SC
(
	Sno varchar(15),
	Cno varchar(10),
	Grade smallint,
	primary key(Sno,Cno), --表级定义主码
	foreign key(Sno) references Student(Sno)
		on delete cascade	--删除Student中的元组时,级联删除SC表中对应的元组
		on update cascade,  --更新Student中的元组时,级联更新SC表中对应的元组
	foreign key(Cno) references Course(Cno)
		on delete no action --删除Course中的元组违反参照完整性时,拒绝执行
		on update cascade	--更新Course中的元组时,级联更新SC表中对应的元组
);

1.3 用户定义的完整性

用户定义的完整性是为满足现实数据规则自定义的属性值规律,如Student表中Sname属性不能取 null,在创建表时定义

create table SC
(
	Sno varchar(15) unique not null, --不能重复且非空
	Cno varchar(10) not null, --非空
	Grade smallint check(Grade>=0 and Grade<=100) --[0,100]开区间
);

create table Student
(
	Sno varchar(15) primary key,
	Sname varchar(10) not null,
	Ssex varchar(2) check(Ssex in('男','女')) --只能为男或女
);

除了为单个属性设置约束条件,也可为插入的数据设置约束条件

create table Student
(
	Sno varchar(15) primary key,
	Sname varchar(10) not null,
	Ssex varchar(2) check(Ssex in('男','女')), --只能为男或女
	check(Ssex='女' or Sname not like 'Ms.%')
); --男生不能称为...夫人

1.4 完整性约束命名子句

也可使用 constraint 子句在创建表时定义完整性约束,对约束进行命名

create table Student
(
	Sno numeric(6)
		constraint C1 check(Sno between 90000 and 99999),
	Sname varchar(10)
		constraint C2 not null,
	Sage numeric(3)
		constraint C3 check(Sage<30),
	Ssex varchar(2)
		constraint C4 check(Ssex in('男','女'))
); --约束命名为C1、C2、C3、C4

create table Teacher
(
	Eno numeric(4) primary key,
	Ename varchar(10),
	Job varchar(8),
	Salary numeric(7,2),
	Deduct numeric(7,2),
	Deptno numeric(2)
	constraint teacher_refer foreign key(Deptno)
	references Dept(Deptno), --为参照关系约束命名
	constraint sum_salary check(Salary+Deduct>=3000) --工资必须大于3000
);

为约束命名的目的是为了日后删除和更改表中的约束(修改表结构相关使用alter,修改元组使用update)

alter table Student
	drop constraint C1; --删除Student表的约束C1

alter table Student
	add constraint C1 check(Sno between 100 and 200); --添加新的C1约束

alter table Student
	drop constraint C3; --删除Student表的约束C3

alter table Student
	add constraint C3 check(Sage>=10 and Sage<=40); --添加新的C3约束

1.5 断言

声明断言来指定更具一般性的约束,可以涉及多个表或聚集操作的比较复杂的完整性约束,T-SQL中没有 assertion 关键字

create assertion <断言名> <check 语句>
/*create assertion asse_sc_db_num
	check
		(60 >=
			(select count(*)
			from Course,SC
			where SC.Cno=Course.Cno and Course.Cname='数据库')
		); --T-SQL不支持*/

T-SQL中可使用触发器实现类似的功能

1.6 触发器

触发器类似于窗体事件,在发送信号后执行一个函数,SQL中即在对表的增、删、改操作时激活相对应的触发器

create trigger <触发器名>
{before|after} <触发事件> on <表名> --指明所在表,激活的时刻
referencing new|old row as <变量> --指出引用的变量
for each{row|statement} --触发器类型,行级和语句级
[when<触发条件>] <触发动作>

T-SQL中实现上述断言的功能如下:

if(object_id('trg_sc_insert') is not null)
	drop trigger trg_sc_insert;
go

create trigger trg_sc_insert
on SC for insert --不支持before,for相当于after
as
	declare @sum_p int,
			@Sno varchar(15),
			@Cno varchar(10),
			@Grade smallint; --定义自变量
	select @sum_p=count(*) from Course,SC where SC.Cno=Course.Cno and Course.Cname='数据库';
	select @Sno=Sno,@Cno=Cno,@Grade=Grade from inserted; --获取插入的元组的属性值
	if(@sum_p>60)
		begin
			delete SC where Sno=@Sno and Cno=@Cno and Grade=@Grade;
		end
go

T-SQL设置触发器与标准SQL的区别还是很大的,删除了newrow和oldrow,使插入操作和修改操作的触发器在编写时很相似,并使用 begin–end 语句块取代end if等

/*修改成绩大于百分10时在其他表中记录*/
/* T-SQL不支持
create trigger SC_T
after update of Grade on SC
referencing
	oldrow as oldTuple
	newrow as newTuple
for each row
when(newTuple.Grade>=1.1*oldTuple.Grade)
	insert into SC_U(Sno,Cno,oldGrade,newGrade)
	values(oldTuple.Sno,oldTuple.Cno,oldTuple.Grade,newTuple.Grade);
*/

if(object_id('SC_T') is not null)
	drop trigger trg_sc_insert;
go

create trigger SC_T
on SC after update --相当于for
as
	declare @Sno varchar(15),
			@Cno varchar(10),
			@old_Grade smallint, 
			@new_Grade smallint; --定义自变量
	select @Sno=Sno,@Cno=Cno,@new_Grade=Grade from inserted; --获取修改后的属性值
	select @old_Grade=Grade from deleted; --获取修改前的属性值
	if(@new_Grade>=1.1*@old_Grade)
		begin
			insert into SC_U(Sno,Cno,old_Grade,new_Grade)
			values(@Sno,@Cno,@old_Grade,@new_Grade);
		end
go

执行一条修改语句尝试一下

update SC
set Grade=100
where Sno='20191102041' and Cno='5'; --以前76分

select * from SC_U;

在这里插入图片描述
在做一个练习

/*为教师表Teacher教授的工资不能低于4000元*/
/*
create trigger insert_or_update_salary
before insert or update on Teacher
referencing newrow as newTuple
for each row
begin
	if(newTuple.Job='教授' and newTuple.Salary<4000)
		then newTuple.Salary:=4000; --赋值使用 :=
	end if;
end;
不支持*/

create trigger insert_or_update_salary
on Teacher for insert,update
as
	declare @Eno numeric(4,0),
			@Ename varchar(10),
			@Job varchar(8),
			@Salary numeric(7,2),
			@Deduct numeric(7,2),
			@Deptno numeric(2,0);
	select @Eno=Eno,@Ename=Ename,@Job=Job,@Salary=Salary,@Deduct=Deduct,@Deptno=Deptno
	from inserted;
	if(@Salary+@Deduct<4000)
		begin
			update Teacher set Salary=4000 where Eno=@Eno and Ename=@Ename;
		end
go

insert into Teacher
values(15,'王伯成','厕所所长',500,100,15);

insert into Teacher
values(16,'王小成','厕所扫地',5000,100,15);
update Teacher
set Salary=500
where Eno=16;

select * from Teacher;

在这里插入图片描述
删除触发器如下

/*drop trigger insert_or_update_salary on Teacher; --不支持,不能指定表*/
drop trigger insert_or_update_salary; --删除触发器

insert into Teacher
values(20,'王大成','厕所拖地',500,100,15);

select * from Teacher;

在这里插入图片描述

2、存储过程

类似于函数,传入参数,执行相应SQL语句

以下为标准SQL语法,T-SQL不完全支持

create procedure transfer(inAccount int,outAccount int,amount int)
as
	declare totalDepositOut int,
			totalDepositIn int,
			inAccountnum int;
begin
	select total_salary into totalDepositOut from Account where Account_id=outAccount;
	if totalDepositOut is null then
		rollback;
		return;
	end if;
	if totalDepositOut<amount then
		rollback;
		return;
	end if;
	select total_salary into totalDepositIn from Account where Account_id=inAccount;
	if totalDepositIn is null then
		rollback;
		return;
	end if;
	update Account set total_salary=total_salary-amount where Account_id=outAccount;
	update Account set total_salary=total_salary+amount where Account_id=inAccount;
end;

call procedure transfer(1,2,100); --执行

标准SQL和T-SQL区别很大,如下为T-SQL语法

create procedure transfer_account
	@in_id int,
	@out_id int,
	@salary int --定义参数
as
	declare @in_salary int,
			@out_salary int;
	select @in_salary=total_salary from Account where Account_id=@in_id;
	select @out_salary=total_salary from Account where Account_id=@out_id;
	if(@in_salary is null)
		begin
			print '收款账户不存在';
			return;
		end
	if(@out_salary is null)
		begin
			print '汇款账户不存在';
			return;
		end
	if(@out_salary<@salary)
		begin
			print '钱不够';
			return;
		end
	update Account set total_salary=total_salary+@salary where Account_id=@in_id;
	update Account set total_salary=total_salary-@salary where Account_id=@out_id;
go

--1号存款500,2号300
exec transfer_account 1,2,500; --2号向1号汇款500
exec transfer_account 5,1,100; --不存在的5号收款
exec transfer_account 1,6,100; --不存在的6号汇款

exec transfer_account 1,2,100; --2号向1号汇款100,成功

select * from Account;

/*alter procedure transfer_account rename to transfer_salary; --不支持*/
exec sp_rename 'transfer_account','transfer_salary'; --更改存储过程名

drop procedure transfer_salary; --删除存储过程

在这里插入图片描述


T-SQL和标准SQL简直是两个语言

实验5.1 存储过程的建立与使用 一、实验目的 理解存储过程的概念、作用、建立和调用方法。 二、实验原理 使用CREATE PROCEDURE语句创建存储过程,ALTER PROCEDURE语句修改存储过程,DROP PROCEDURE语句删除存储过程存储过程有不带参数的、有带输入参数的、有带输出参数(output)的,还可以有带返回值的。创建好的存储过程可以使用EXEC procedure_name语句执行。 实验5.2 触发器的建立与使用 一、实验目的 理解触发器的概念和作用;了解触发器的分类及触发条件;掌握触发器的定义及应用。 二、实验原理 1、 使用CREATE TRIGGER语句定义触发器,ALTER TRIGGER语句修改触发器,DROP TRIGGER语句删除触发器。 2、 触发器分AFTER/FOR和INSTEAD OF两种类型:AFTER/FOR类型的触发器是在相应的触发语句(insert、delete、update)执行完后被触发的。如果触发语句对应的表上有完整性约束,这些完整性约束必须不违背时,相应的触发语句才能执行,然后才能触发对应的AFTER/FOR类型的触发器。INSTEAD OF类型的触发器会在触发语句(insert、delete、update)执行之前被触发,并取代相应的触发语句。 3、 在表或视图上,每个INSERT、UPDATE或DELETE语句只能创建一个INSTEAD OF类型的触发器,无法为有外键约束且指定为级联删除或级联修改的表创建DELETE或UPDATE语句上的INSTEAD OF 类型的触发器。 SQL SERVER为每个触发器都创建了两个临时表INSERTED表和DELETED表,这两个表的逻辑结构与被触发器作用的表一样,用户可以读取这两个表的内容,但不能对它们进行修改,触发器执行完后,这两个表也会自动删除。当执行INSERT时,INSERTED表中保存要向表中插入的所有行;当执行DELETE时,DELETED表中保存要从表中删除的所有行;当执行UPDATE时,修改前的行保存在DELETED表中,修改后的行保存在INSERTED行中。
一、实验目的 1.掌握SQL Server 2005的安装。 2.掌握SQL Server Management Studio的启动和使用。 3.掌握SQL Server 2005服务器的配置和注册。 4.掌握SQL Server 2005查询的基本使用。 5.掌握应用SQL Server Management Studio创建数据库的方法。 6.掌握应用SQL Server Management Studio修改和查看数据库的方法。 7.掌握应用SQL Server Management Studio删除数据库的方法。 8.掌握应用Transact-SQL语句创建数据库的方法。 9.掌握应用Transact-SQL修改和查看数据库的方法。 10.掌握通过Transact-SQL删除数据库的方法。 11.掌握SQL Server 2005数据库和操作系统物理文件的关系。 12.掌握数据库的分离和附加方法。 二、实验内容 1.完成SQL Server 2005开发版的安装。 提示:若计算机系统中已经安装有SQL Server 2005系统,则在安装时需要选择安装命名实例。安装过程中身份验证模式选择“混合模式”并设置sa账户的密码。 2.利用SQL Server配置管理器启动、停止SQL Server服务(包括默认实例和命名实例),配置SQL Server服务为自动启动。 3.利用SQL Server配置管理器配置进行SQL Server 2005网络配置,启用默认实例和命名实例的TCP/IP协议。 4.利用SQL Server外围配置器配置数据库引擎的服务及远程连接,设置为“本地连接和远程连接”,选择“同时使用TCP/IP和named pipes”。 5.利用SQL Server Management Studio注册安装的命名实例。 6.利用SQL Server Management Studio注册远程服务器。 提示:注册远程服务器时需要使用混合验证模式,利用sa账户和密码登录远程服务器。 7.启动SQL Server Management Studio,连接到服务器。新建一个查询,在其中输入如下代码: DECLARE @position int, @string char(5) SET @position = 1 SET @string = 'China' WHILE @position <= DATALENGTH(@string) BEGIN SELECT SUBSTRING(@string, @position, 1) 字符, ASCII(SUBSTRING(@string, @position, 1)) ASCII码 SET @position = @position + 1 END
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值