zoukankan      html  css  js  c++  java
  • SqlServer:存储过程

    存储过程

    存储过程(Stored Procedure)简称过程,由一系列SQL语句构成完成一定的功能的程序段,通过过程名调用并执行。在 SqlServer 中存放在数据库的“可编程性”组件中,与表和视图的级别相同。存储过程是由流程控制和 SQL 语句组成的,允许用户声明变量,可以调用系统函数,经编译后存储在数据库服务器中。存储过程可以接收输入参数,也可以将运行结果带出过程,返回执行存储过程的状态值,还可以嵌套调用。由于存储过程在服务器运行,且运行后会保存在缓存中,因此可以提高运行效率。
    存储过程分为三类,分别是系统存储过程、用户自定义存储过程和扩展存储过程。

    存储过程类型 说明
    系统存储过程 系统自动创建的系统存储过程,用于显示各种参数等,以 “sp_” 为前缀
    自定义存储过程 由用户为完成某一特定功能而编写的存储过程,名称不能以 “sp_” 为前缀
    扩展存储过程 是对动态链接库(DLL)函数的调用,前缀名是 “XP_”

    创建存储过程的步骤是:

    1. 检验存储过程名是否存在;
    2. 编写存储过程中的 SQL 语句;
    3. 用创建存储过程的语法创建存储过程。

    SQL 语句

    建立存储过程前需要确定其功能,存储过程的调用可以是无参数调用或有参数调用,可以有返回值或者没有参数返回。建立存储过程的命令格式是:

    CREATE PROCEDURE 存储过程名
    [WITH ENCRYPTION]
    [@参数名 类型 [ = 默认值][OUTPUT]][,-n ]
    AS SQL语句
    
    参数 说明
    PROCEDURE 存储过程名
    WITH ENCRYPTION 将存储过程的代码加密
    @参数名 类型 接收指定的实际参数及类型
    OUTPUT 表示参数是输出参数,若无此项则参数是输入参数
    SQL 语句 是构造存储过程的 SQL 语句,如果包括多条命令可以用 BEGIN…END 代码块

    调用存储过程的方式有以下 2 种:

    存储过程名 [参数值]    --存储过程名是批处理的第 1 条语句
    EXECUTE 存储过程名 [参数值]    --存储过程名不是批处理的第 1 条语句
    

    存储过程样例

    样例一

    此时有成绩表 Score 和课程表 Course,表中具有以下字段和记录。


    用户输入某一门课程的名称,就可统计出该课程各分数段分布的人数。首先建立排名表:

    CREATE TABLE Rank(
        division char(20),
        sub_sum int
    );
    
    INSERT INTO Rank(division) VALUES('[0,60)'),('[60,70)'),('[70,80)'),('[80,90)'),('[90,100]');
    

    接着创建存储过程。

    CREATE PROCEDURE printcourse @pcname char(20)
    AS
        DECLARE @pcno char(20), @pcount int, @count int
        set nocount on
        SELECT @count = COUNT(*) FROM Course WHERE Cname = @pcname
        IF(@count = 0)
             BEGIN
                 RAISERROR('您输入的课程不存在,请重新输入!', 16, 1)
                 RETURN
             END
        
        --查找 @pcname 对应的课程号	 
        SELECT @pcno = Score.cno FROM Course, Score WHERE Course.Cno = Score.Cno AND Course.Cname = @pcname
        --统计不及格人数,并更新 Rank 表
        SELECT @pcount = COUNT(*) FROM Score WHERE Degree < 60 AND Cno = @pcno
        UPDATE Rank SET sub_sum = @pcount WHERE division = '[0,60)'
        
        SELECT @pcount = COUNT(*) FROM Score WHERE Degree >= 60 AND Degree < 70 AND Cno = @pcno
        UPDATE Rank SET sub_sum = @pcount WHERE division = '[60,70)'
    
        SELECT @pcount = COUNT(*) FROM Score WHERE Degree >= 70 AND Degree < 80 AND Cno = @pcno
        UPDATE Rank SET sub_sum = @pcount WHERE division='[70,80)'
    
        SELECT @pcount = COUNT(*) FROM Score WHERE Degree >= 80 AND Degree < 90 AND Cno = @pcno
        UPDATE Rank SET sub_sum = @pcount WHERE division='[80,90)'
    
        SELECT @pcount = COUNT(*) FROM Score WHERE Degree >= 90 AND Degree <= 100 AND Cno = @pcno
        UPDATE Rank SET sub_sum = @pcount WHERE division = '[90,100]'
    

    最后尝试执行该存储过程。

    EXEC printcourse '计算机导论'
    
    SELECT * FROM Rank
    

    样例二

    统计某一门课的平均成绩,存储过程可带有一个字符型参数值,接受用户输入的课程名称。一个输出参数(用 output 声明)用于存放返回给调用者的这门课程的平均成绩)。

    CREATE PROCEDURE printavg_course @pcname char(20), @pavg int output
    AS
    
        DECLARE @pcno char(20)
        SET NOCOUNT ON
        SELECT @count = COUNT(*) FROM Course WHERE Cname = @pcname
        IF(@count = 0)
             BEGIN
                 RAISERROR('您输入的课程不存在,请重新输入!', 16, 1)
                 RETURN
             END
    
             --最关键的 2 行
         SELECT @pcno = Score.cno FROM Course, Score WHERE Course.Cno = Score.Cno AND Course.Cname = @pcname
         SELECT @pavg = AVG(Score.Degree) FROM Score WHERE Cno = @pcno
         PRINT RTrim(@pcname) + '的平均成绩为:' + CAST(@pavg AS char(5))
    

    运行该存储过程。

    DECLARE @pavg int
    
    EXEC printavg_course '操作系统', @pavg output
    
    Select @pavg int
    

    样例三

    在 Course 表中查询学生的学号、课程号和成绩,但是要将学生选课成绩从百分制改为等级制,即 A、B、C、D、E 五级。

    CREATE PROCEDURE printclass_degree 
    AS
        SELECT Sno, Cno, Degree,
        CASE
             WHEN Degree <  60                   THEN '不及格'
             WHEN Degree >= 60 AND Degree < 70   THEN '及格'
             WHEN Degree >= 70 AND Degree < 80   THEN '中'
             WHEN Degree >= 80 AND Degree < 90   THEN '良'
             WHEN Degree >= 90 AND Degree <= 100 THEN '优'
             ELSE '成绩为空!'
        END AS 'Degree  Classified'
        FROM Score
    

    运行该存储过程。

    EXEC printclass_degree 
    

    样例四

    表 Course 增加两列,分别是课程选修最大人数(mn ,默认50)和当前人数(cn ,默认0)。

    某学生没有选过某课程,要选某课程且没有超过课程最大人数时,可以选择该课程,当前选课人数加1,并在成绩 Score 表中增加对应的该生该课程的成绩为 0 记录。否则,提示该课程选课人数已满,不能选课。

    CREATE PROCEDURE cs @sno char(3), @cno char(5)
    AS
    	DECLARE @mn INT, @cn INT, @count INT
    	SET @count = (SELECT count(Sno) FROM Score WHERE Sno = @sno AND Cno = @cno)
    	IF(@count = 1)
    	BEGIN
    		RAISERROR('该学生已经选过这门课',16,1)
    	END
    	ELSE
    	BEGIN
    		SELECT @mn = mn FROM Course WHERE Cno = @Cno
    		SET @count = (SELECT count(Sno) FROM Score WHERE Cno = @Cno)
    
    		IF(@count >= @mn)
    		BEGIN
    			RAISERROR('该课程已达到最大选课人数',16,1)
    		END
    		ELSE
    		BEGIN
    			UPDATE Course SET cn = @count + 1 WHERE Cno = @cno
    			INSERT INTO Score(Sno, Cno, Degree) VALUES(@sno, @cno, 0)
    			RAISERROR('学生选课成功',16,1)
    		END
    	END
    

    运行该存储过程。

    EXEC cs '101', '3-245'
    SELECT * FROM Score
    SELECT * FROM Course
    

    EXEC cs '101', '3-235'
    


    某学生选了某课程后要退选,该课程的当前选课人数减 1 并删除其对应的成绩。

    CREATE PROCEDURE csd @sno char(3), @cno char(5)
    AS
    	DECLARE @mn INT, @cn INT, @count INT
    	SET @count = (SELECT count(Sno) FROM Score WHERE Sno = @sno AND Cno = @cno)
    	IF(@count = 0)
    	BEGIN
    		RAISERROR('该学生没有选过这门课',16,1)
    	END
    	ELSE
    	BEGIN
    		SELECT @cn = cn FROM Course010 WHERE Cno = @Cno
    		UPDATE Course SET cn = @cn - 1 WHERE Cno = @cno
    		DELETE Score WHERE Sno = @sno AND Cno = @cno
    		RAISERROR('学生退课成功',16,1)
    	END
    

    运行该存储过程。

    EXEC csd '101', '3-245'
    SELECT * FROM Score
    SELECT * FROM Course
    

    EXEC csd '101', '3-245'
    


    某学生选了某课程后,可以查询其成绩(out)。

    CREATE PROCEDURE cx @sno char(3), @cno char(5)
    AS
    	DECLARE @mn INT, @cn INT, @count INT
    	SET @count = (SELECT count(Sno) FROM Score WHERE Sno = @sno AND Cno = @cno)
    	IF(@count = 0)
    	BEGIN
    		RAISERROR('该学生没有选过这门课',16,1)
    	END
    	ELSE
    	BEGIN
    		SELECT * FROM Score WHERE Cno = @cno AND Sno = @sno
    	END
    

    运行该存储过程。

    EXEC cx '101', '3-245'
    


    如果学生没有选课,则看到如下信息。

    参考资料

    《SqlServer 2014 数据库技术实用教程》,胡伏湘、肖玉朝 主编,清华大学出版社

  • 相关阅读:
    Weblogic_Server与EJB
    EXTJS中的表格控件(一)
    Javascript trim()函数实现
    Ajax技术的基础
    一个Ajax简单实例分析
    jQuery学习之四document ready文档就绪函数
    jQuery学习之八jQuery解析xml文件(摘录)
    jQuery学习之七jQuery效果
    jQuery学习之二css操作
    jQuery学习之六重命名jQuery库
  • 原文地址:https://www.cnblogs.com/linfangnan/p/14824770.html
Copyright © 2011-2022 走看看