大型数据库期末复习(索引-存储过程-函数-游标-触发器-事务)

大型数据库期末复习-索引-存储过程-函数-游标-触发器-事务

实验一

重要代码

USE 教学管理
SELECT 姓名,课名,CASE
				WHEN 成绩 < 60 THEN '不及格'
				WHEN 成绩 < 80 THEN '及格'
				ELSE '优秀'
				END AS '等级成绩'
SQL语句。。。。

索引

基本格式

CREATE UNIQUE NONCLUSTERED
INDEX student_IDnumber
ON dbo.学生表(身份证号)
WITH(FILLFACTOR=80)

唯一性:unique
非聚集索引:nonclustered
聚集索引:clustered index
填充因子:fillfactor
注意
连接表的时候用on
删除索引

drop index student_IDnumber on dbo.学生表

这里的student_IDnumber和学生表都是自己自定义的

例子

CREATE CLUSTERED INDEX QQQ ON TEMP(身份证号)
SELECT 学号,身份证号,姓名 FROM dbo.TEMP
WHERE 专业='计算机'  ORDER BY 身份证号 DESC

聚集索引:clustered index

存储过程

基本格式

CREATE PRODUCER P1
AS
BEGIN
SELECT 姓名,籍贯 FROM DBO.学生表
END

三种执行方式
P1
EXEC P1
EXECUTE P1

带参数的存储过程
注意:定义存储过程的时候可以给参数加括号但是执行的时候一定不能加括号

CREATE PRODUCER P3 @CHENGJI INT
AS
BEGIN
SELECT * FROM DBO.学生表 WHERE 学号 in (select 学号 from dbo.选课表)
GROUP BY 学号
END
GO
//执行
EXEC P3 90

样例4

CREATE PRODUCER P4 @CHENGJI INT = 60
AS
BEGIN
//SQL语句
END
//执行
EXEC P4//没给参数按照默认值来
EXEC P4 DEFAULT//没给参数都按照默认值来
EXEC P4 80//传参就按照传参来计算

注意默认值跟在INT后面
字符串默认值样例

CREATE PRODUCER P5 @C VARCHAR(20) = '王'
AS
BEGIN
//SQL语句
END

有OUTPUT参数返回的样例

CREATE PRODUCER P6 @KAIKEHAO VARCHAR(20),@PINGJUNFEN FLOAT OUTPUT,@ZUIGAOFEN INT OUTPUT,@ZUIDIFEN INT OUTPUT
AS
BEGIN
SQL语句
END
执行:
DECLARE 下面这四个变量并赋初值
EXEC P6 @KAIKEHAO,@PINGJUNFEN OUT,@ZUIGAOFEN OUT,@ZUIDIFEN OUT
**注意这里的out可以换成output但是不能不加**

有返回值的存储过程样例

CREATE PRODUCER P7 @C VARCHAR(20)
AS
BEGIN
DECLARE @NUM INT
SELECT @NUM = COUNT(*) FROM DBO.学生表
WHERE 籍贯 LIKE ...
IF(@NUM > 1) RETURN 1
ELSE IF(@NUM = 1) RETURN 0
ELSE RETURN -1
END
所以在执行的时候需要接收返回值
DECLARE @RESULT INT
EXEC @RESULT = P7 '杭州'
这里的RESULT就有三种值的可能注意区分

多参数存储过程样例

CREATE PRODUCER P8 @XUEHAO VARCHAR(20),@JIGUAN VARCHAR(100)
AS
BEGIN
SQL语句
END
执行:
EXEC P8 'S060101','成都'
直接将多个参数用逗号隔开

函数

注意:函数的参数必须加括号,存储过程可以加也可以不加,但是存储过程在执行的时候一定不能加,函数在执行的时候也是必须加的
注意:函数的返回值 RETURNS 必须有S,后面还得跟上返回值类型
各种不同类型的函数的返回值类型一定不一样!!

普通函数:RETURN类型和RETURNS类型一样
标量函数:RETURN类型和RETURNS类型一样
内嵌表函数:RETURNS类型是一个TABLE,RETURN也应该是一个TABLE
多语句表值函数:RETURNS是一个自定义的表,最后直接RETURN,不加任何东西

基本格式

CREATE FUNCTION F1(@N INT)
RETURNS BIGINT
AS
BEGIN
DECLARE @RESULT INT
SQL语句
RETURN @RESULT
END

标量函数样例2

CREATE FUNCTION F2(@ZHUANYE VARCHAR(20))
RETURNS INT
AS
BEGIN
DECLARE @NUM INT
RETURN @NUM
END

内嵌表函数样例
注意返回值是一个table类型的

CREATE FUNCTION F3(@ZHUANYE VARCHAR(20))
RETURNS TABLE
AS
RETURN( SELECT 学号,姓名,性别,籍贯 FROM DBO.学生表 WHERE 专业 = @ZHUANYE)
GO

多语句表值函数样例

CREATE FUNCTION F4(@CHENGJI INT)
RETURNS @RESULT TABLE(
	学号 VARCHAR(20),
	姓名 VARCHAR(20),
	性别 VARCHAR(20),
	籍贯 VARCHAR(20)
)
AS
BEGIN
SQL语句
RETURN
END

游标

游标类型:
1.只读游标 INSENSITIVE
2.可写游标SCROLL

基本格式(只读游标)

DECLARE CUR1 INSENSITIVE CURSOR
FOR
SQL语句(作为游标所在表)
OPEN CUR1
定义一系列变量
//遍历
FETCH NEXT FROM CUR1 INTO 定义的变量
WHILE (@@FETCH_STATUS = 0)
BEGIN
	SQL操作语句
	FETCH NEXT FROM CUR1 INTO 定义的变量
END
CLOSE CUR1
DEALLOCATE CUR1
GO

绝对位置游标样例

针对学生表定义一个游标,将游标中绝对位置为3的学生姓名改为你的姓名,并将性别改为你的性别

DECLARE CUR3 SCROLL CURSOR
FOR
SELECT * FROM DBO.学生表
OPEN CUR3
FETCH ABSOLUTE 3 FROM CUR3
IF(@@FETCH_STATUS = 0)
	UPDATE语句
CLOSE CUR3
DEALLOCATE CUR3

首尾位置的游标样例

DECLARE CUR4 SCROLL CURSOR
FOR
SQL语句
OPEN CUR4
//直接fetch首尾位置的数据
FETCH FIRST FROM CUR4
FETCH LAST FROM CUR4
CLOSE CUR4
DEALLOCATE CUR4

触发器

使用 SELECT * INTO创建表备份
SELECT * INTO 学生表_备份  FROM DBO.学生表 WHERE 1 = 2
删除:
DROP TABLE 学生表备份

创建替代触发器样例

CREATE TRIGGER TR1 ON DBO.选课表
INSTEAD OF UPDATE
AS
BEGIN
IF(COLUMNS_UPDATED() = 4)
	BEGIN
	UPDATE语句
	END
END
GO

创建UPDATE触发器

CREATE TRIGGER TR2 ON DBO.选课表 
FOR UPDATE
AS
BEGIN
SQLUPDATE语句
END
GO

创建DELETE触发器

CREATE TRIGGER TR3 ON DBO.学生表
FOR DELETE
AS
BEGIN
SQL语句
END
GO

删除TRIGGER

DROP TRIGGER TR1,TR2,TR3

事务

基本知识

SET XACT_ABORT OFF情况下:
自动事务:只有错误的语句不执行,其他的都会执行
隐式事务:只有错误的语句不执行,其他的都会执行
显示事务:只有错误的语句不执行,其他的都会执行
如果显示事务带有TRY CATCH那么不管SET XACT_ABORT 是开或是关都执行全部回滚
SET XACT_ABORT ON情况下:
自动事务:错误的语句后面都不会执行
显示事务:一旦遇到错误,整个事务都会回滚,所有的数据都插入失败,因此没有数据插入
隐式事务:一旦遇到错误,整个事务同样会回滚(注意delect语句也会被回滚)

事务隔离级别

脏读样例READ UNCOMMITTED

BEGIN TRAN
update dbo.选课表  set 成绩=100 where 成绩>=80
WAITFOR DELAY '00:00:15'
ROLLBACK TRAN
在另一个查询执行如下
在查询1执行的15秒内(如果操作较慢可修改上面的等待时间),查询2执行如下语句:
SET Transaction Isolation Level Read UNCOMMITTED
SELECT * FROM dbo.选课表  WHERE 成绩 IS NOT NULL

分析:
隔离级别:READ UMCOMMITTED
第二个查询会立即执行,第二个查询会读到第一个查询执行的中间结果因为查询二隔离的级别为READ UNCOMMITTED 运行脏读

READ COMMITTED

BEGIN TRAN
update dbo.选课表  set 成绩=100 where 成绩>=80
WAITFOR DELAY '00:00:15'
ROLLBACK TRAN
在另一个查询执行如下
在查询1执行的15秒内(如果操作较慢可修改上面的等待时间),查询2执行如下语句:
SET Transaction Isolation Level Read COMMITTED
SELECT * FROM dbo.选课表  WHERE 成绩 IS NOT NULL

分析:
隔离级别:READ COMMITTED
第二个查询会等第一个查询执行完再执行,第二个查询会读到第一个查询回滚后的结果,因为隔离级别为READ COMMITTED ,不允许读取未提交的数据

加锁 WITH(NO LOCK)

BEGIN TRAN
update dbo.选课表 WITH(XLOCK) set 成绩=100 where 成绩>=80
WAITFOR DELAY '00:00:15'
ROLLBACK TRAN
在另一个查询执行如下
在查询1执行的15秒内(如果操作较慢可修改上面的等待时间),查询2执行如下语句:
SELECT * FROM dbo.选课表 WITH(NOLOCK)  WHERE 成绩 IS NOT NULL

分析:
查询二立即执行,执行结果是查询一的中间结果。查询中使用WITH(NOLOCK)这种方式就相当于READ UNCOMMITTED.当查询一执行完之后再执行查询二结果就是查询一回滚后的结果,与未提交的过程一样。

共享锁样例

BEGIN TRAN
update dbo.选课表 WITH(XLOCK) set 成绩=100 where 成绩>=80
WAITFOR DELAY '00:00:15'
ROLLBACK TRAN
在另一个查询执行如下
在查询1执行的15秒内(如果操作较慢可修改上面的等待时间),查询2执行如下语句:
SELECT * FROM dbo.选课表 WITH(HOLDLOCK)  WHERE 成绩 IS NOT NULL
分析:

查询2会等待15秒然后再执行查询成绩。因为加了共享锁,所以相当于READ COMMITTED.

你可能感兴趣的:(数据库,sql)