zoukankan      html  css  js  c++  java
  • 数据库——SQL SERVER Transact-SQL 程序设计

    什么是Transact-SQL?

    标准SQL不支持过程化控制, 不能完成复杂的功能.
    T-SQL是过程化SQL语言,   是SQL的扩展
    增加了过程化语句 (变量,赋值,分支,循环...)
    是数据库服务器端的编程,不同于客户端的应用程序
    不是标准语言  (ORACLE中称为PL/SQL)
    作用:
    编写批处理、存储过程,函数,触发器

    一 SQL-SERVER批处理

    下面的示例创建两个批处理。

    USE STUDB          --这是使用STUDB数据库
    GO               
    
    DECLARE @RS int                 /* 定义变量@RS */
    SET   @RS =  (SELECT COUNT(*)         /* 变量赋值 */
          FROM STUDENT
          WHERE SDEPT='CS' )
    PRINT '计科学院学生人数 ' + CAST(@RS AS char (3))
    GO

    用GO 命令结束一个批处理
    两种类型的注释方式
    一般保存到批处理文件中,以后打开执行,文件名后缀为.SQL

    控制语句

    BEGIN...END

    BEGIN...END:一组要执行的 T-SQL 语句可以包含在 BEGIN...END 中。相当于C语言的复合语句{ }
     语法:

    BEGIN 
     { 
      statement 
      | statement_block
     } 
    END

    其中,statement 为语句,statement_block 为语句块。

    IF...ELSE

    IF...ELSE:可以根据指定的条件来执行不同的SQL 语句。

    语法:

    IF Boolean_expression 
        { sql_statement|statement_block } 
    ELSE 
        { sql_statement|statement_block } 

    IF 语句示例:

    IFSELECT COUNT(*) FROM SC WHERE CNO=1 )>20--单值子查询可以当做表达式
       BEGIN 
         ……
       END 
    ELSE
       BEGIN 
         ……
       END

    WHILE 循环

    WHILE:可以根据某些条件来执行一条 SQL 语句或一组语句。只要指定的条件为真,则重复执行该语句。

    语法:

    WHILE Boolean_expression    
    { 
          statement | statement_block 
    }   
          BREAK     
    { 
          statement | statement_block 
    }   
         CONTINUE 

    例题:
    给1号课加分,如果平均分少于 75,每人加1分,如果最高分已经达到95,则停止加分 。

    USE STUDB    
    GO 
    WHILE (SELECT AVG(GRADE) FROM SC WHERE CNO=1) < 75 --单值子查询可以当做表达式
    BEGIN                           --循环体用BEGIN END
      IF (SELECT MAX(grade) FROM SC WHERE CNO=1) >= 95  
          BREAK  
      UPDATE SC 
        SET GRADE=GRADE+1 WHERE CNO=1
    END
    
    PRINT '调整完成!'
    GO

    变量

    两种类型的变量:                
    全局变量
        全局变量是SQL Server系统内部使用的变量,任何程序均可调用。
    局部变量
      自定义变量, 作用于局部

    全局变量:


    SQL Server 中的全局变量都用'@@' 标记作为前缀。

    可以使用PRINT 输出全局变量的值。

    输出SQL SERVER版本

    PRINT @@VERSION

    输出上一个SQL语句影响的行数

    SELECT * FROM SC WHERE CNO=1 
    PRINT  @@ROWCOUNT 

    局部变量:

    局部变量名必须以 '@' 为前缀, 先定义,再使用。用DECLARE定义, 类型同表的列类型。

    作用域:声明局部变量的批处理、存储过程或语句块。

    DECLARE   @姓名         CHAR(20)
    DECLARE   @年龄         INT
    DECLARE   @工资         FLOAT
    DECLARE   @地址         VARCHAR(40)
    DECLARE   @SNO         NUMERIC(5), @SNAME   CHAR(6),  @SAGE    INT

    注意:变量的初值为空值null !

    两种方法为变量赋值

    SET 语句或 SELECT 语句用于给局部变量赋值。

    DECLARE @姓名  CHAR(10), @年龄 INT
    SET @姓名 ='刘晨'     --SET一次只能赋值一个变量
    --赋值单值子查询结果
    SET @姓名 = (SELECT SNAME FROM STUDENT WHERE SNO=95001)

    或:

    
    
    DECLARE @姓名  CHAR(10), @年龄 INT
    SELECT
    @姓名 ='刘晨',@年龄=20 --SELECT可多 赋值 --赋值单值查询结果 SELECT @姓名 = SNAME, @年龄=SAGE
    FROM STUDENT
    WHERE SNO=95001

    注意这里给赋值单值子查询SET SELECT的区别,SELECT已经有了一个SELECT所以可以省去不写,但SET必须写,否则会报错!!

    SET @CCOURSE =( SELECT COUNT(*) FROM   SC WHERE SNO=@SNO )--SET必须写SELECT
    SELECT @AVG =(SELECT AVG(GRADE) FROM SC WHERE SNO=@SNO) 
    SELECT @AVG = AVG(GRADE) 
    FROM SC
    WHERE SNO=@SNO --SELECT可以省去不写

    局部变量的使用实例:

    DECLARE @姓名  CHAR(10)
    SET @姓名 ='刘晨'
    SELECT *  FROM STUDENT 
        WHERE SNAME=@姓名--变量可以用在SQL语句中
    GO

    变量值的输出

    格式一:单表达式输出
    功能:一次只能输出一个局部变量值或一个表达式的值。
    例句:

    print @x+4
    print @y


    格式二: 多表达式输出
    功能:一次可输出若干个局部变量值或表达式的值。按查询表的格式输出,一般不用。
    例句:

    select @x, @y+100

    T-SQL语法总结

    变量定义:     DECLARE  @变量名  类型
    变量赋值:     SET @变量=表达式
                 SET @变量=( 单值子查询 )
                 SELECT @变量1=表达式1,@变量2=表达式2
                 SELECT @变量1=列1,@变量2=列2  FROMWHERE 条件
    输出:        PRINT ‘输出结果是’+CAST( @变量名  AS  CHAR(3))
    条件:        IF  条件表达式
                     语句          /*多条语句要用BEGIN  END*/
                 ELSE
                     语句          /*多条语句要用BEGIN  END*/
    循环:        WHILE   条件表达式
                 BEGIN
                      语句
                 END 

    二   SQL-SERVER 存储过程

    什么是存储过程?

    存储过程(procedure)类似于C语言中的函数
    存储过程可以带参数。

    void  sum(int a,int b)
    {  
       int s;
       s =a+b;
       printf("sum=%d
    ", s) ;
    }

    存储过程的分类

    系统存储过程
    由系统定义,存放在master数据库中,类似C语言中的系统函数,系统存储过程的名称都以“sp_”开头

    用户自定义存储过程
    由用户在自己的数据库中创建的存储过程,经编译和优化后存储在数据库服务器中,使用时只要调用即可。类似C语言中的用户自定义函数。

    常用的系统存储过程:

    如何创建存储过程?

    创建存储过程的语法

    CREATE  PROCEDURE  存储过程名 [参数]
    AS
       SQL语句
    GO


    执行存储过程的语法

    EXEC  存储过程名  [参数]

    建立存储过程, 显示计科学院的学生人数:

    CREATE  PROCEDURE  CSCOUNT 
        AS
    DECLARE @RS int                 /* 定义变量@RS */
    SET   @RS =  (SELECT COUNT(*)         /* 变量赋值 */
          FROM STUDENT
          WHERE SDEPT='CS' )
    PRINT '计科学院学生人数 ' + CAST(@RS AS char (3))
    GO

    执行存储过程语句:

    EXEC  CSCOUNT

    创建不带参数的存储过程

    问题:计算机等级考试分为笔试成绩和机试成绩,
        请创建存储过程,查看本次考试平均分以及未通过考试的学员名单
    需要定义什么变量?  

    CREATE PROCEDURE proc_stu   --proc_stu为自定义的存储过程名
      AS
        DECLARE @writtenAvg float,@labAvg float
        SELECT @writtenAvg=AVG(writtenExam),
               @labAvg=AVG(labExam)  FROM Marks
        print '笔试平均分:'+CAST(@writtenAvg AS CHAR(3))  
        print '机试平均分:'+CAST(@labAvg AS CHAR(3))
        IF (@writtenAvg>70 AND @labAvg>70) --显示考试成绩的等级 
           print '本班考试成绩:优秀'
        ELSE
           print '本班考试成绩:较差'
        print '--------------------------------------------------'
        print '           参加本次考试没有通过的学员:'
        SELECT stuName,stu.stuNo,writtenExam,labExam--显示未通过的学员
        FROM  stu, Marks
        WHERE stu.stuNo=Marks.stuNo AND (writtenExam<60 OR labExam<60)
    GO

    调用存储过程

    EXEC    PROC_STU

    带输入参数的存储过程

    CREATE  PROCEDURE  DEPTCOUNT 
        @DEPT  CHAR(2)     /* 参数变量 注意位置  无关键字DECLARE*/
    AS
    DECLARE @RS int                 /* 定义变量@RS */
    SET   @RS =  (SELECT COUNT(*)         /* 变量赋值 */
          FROM STUDENT
          WHERE SDEPT=@DEPT )
    PRINT @DEPT+'学院学生人数 ' + CAST(@RS AS char (3))
    GO

    执行存储过程语句:

    EXEC  DEPTCOUNT   'CS' 

    练习: 建立过程 PSTU, 输出某学生的姓名和总学分.
    过程参数?    变量?   代码?

    DROP PROCEDURE PSTU
    GO
    CREATE PROCEDURE PSTU 
    @SNO INT
      AS
        DECLARE @NAME CHAR(20)
        DECLARE @TOTAL INT
        SELECT @NAME=SNAME FROM STUDENT WHERE SNO=@SNO
        SELECT @TOTAL=SUM(CCREDIT) FROM COURSE,SC
        WHERE SC.SNO=@SNO AND SC.CNO=COURSE.CNO
        PRINT'Name='+@NAME+'Total credit='+CAST(@TOTAL AS CHAR(3))
    GO

    如何执行?

    EXEC   PSTU  95001

    练习:
    建立过程 PSTU2, 输出某学生的姓名, 选课门数, 平均分, 最高分,最低分, 总学分, 如果总学分<9,则显示“此学生学分不足!”,否则显示“此学生学分已足!”,

    过程参数?    变量?   代码?

    DROP PROCEDURE PSTU2
    GO
    
    CREATE PROCEDURE PSTU2
    @SNO INT
      AS
        DECLARE @NAME CHAR(20),@CCOURSE INT,@TOTAL INT,@AVG INT
        SELECT @NAME=SNAME FROM STUDENT WHERE SNO=@SNO
        SELECT @CCOURSE =COUNT(*) FROM   SC WHERE SNO=@SNO 
        SELECT @TOTAL= SUM(CCREDIT) FROM COURSE,SC WHERE SC.SNO=@SNO AND SC.CNO=COURSE.CNO
        SELECT @AVG = AVG(GRADE) FROM SC WHERE SNO=@SNO 
        PRINT'Name='+@NAME+    '选课门数'+CAST(@CCOURSE AS CHAR(5))+'平均分'
        +CAST(@AVG AS CHAR(5))+'Total credit='+CAST(@TOTAL AS CHAR(3))
        IF(@TOTAL<9)
        PRINT '此学生学分不足!'
        ELSE
        PRINT '此学生学分已足!'
    GO

    如何执行?
        EXEC   PSTU2  95001

     

    总结  

    存储过程是一组预编译的SQL语句,它可以包含数据操纵语句、变量、逻辑控制语句等
    定义存储过程的语法:
      

    CREATE  PROCEDURE  存储过程名
        @参数1  数据类型,
         …… ,
        @参数n  数据类型
     AS
         SQL语句
     GO


    EXECUTE(执行,调用)存储过程的语法:

     EXEC  过程名  [参数]

    存储过程的优点

    经编译和优化后存储在数据库服务器中,运行效率高
    客户端应用程序可以调用
    降低客户机和服务器之间的通信量
    有利于集中控制,方便维护

    三 SQL-SERVER 游标

    什么是游标?

    先看一个例子:
       设计一个存储过程,参数是课号,显示某门课的优、良、中、及格、差的人数。

    输出某门课优良差人数 实现方法1

    CREATE PROCEDURE P1  
    @CNO INT    --参数为课号
    AS
    DECLARE @优 int,@良 int,@差 int
    SET  @优=( SELECT COUNT(*) FROM SC WHERE CNO=@CNO AND GRADE>=90 )
    SET   @良=( SELECT COUNT(*) FROM SC WHERE CNO=@CNO AND GRADE>=80 AND GRADE<90 )
    SET   @差=( SELECT COUNT(*) FROM SC WHERE CNO=@CNO AND GRADE<80 )
    PRINT '优人数'+CAST(@优 AS CHAR(2))+' 良人数'+CAST(@良 AS CHAR(2)) +' 差人数'+CAST(@差  AS CHAR(2))
    GO

    多遍扫描SC, 效率低

    游标(cursor)

    SQL查询结果是记录的集合
    可将SQL语句的查询结果定义为游标,游标代表一个查询结果集合
    可以逐一从游标中获取记录,进行处理。

    游标操作分为四步:
              1、声明游标:
                DECLARE 游标名 CURSOR FOR
                     SELECT查询
               2、打开游标
               3、循环从游标中提取数据
               4、关闭游标

    输出某门课优良差人数 实现方法2,使用游标:
    将选某门课的成绩(这是一个查询)定义为一个游标,对游标中的成绩循环判断,统计

    DROP PROCEDURE P1
    GO
    
    CREATE PROCEDURE P1  
    @CNO INT 
    AS
    DECLARE @成绩 int,@优 int,@良 int,@差 int
    DECLARE C1 CURSOR FOR        /*定义游标*/
           SELECT GRADE FROM SC WHERE CNO=@CNO
    SELECT  @优=0,@良=0,@差=0     /*计数变量清零(原初值为null) */
    OPEN C1      /*打开游标—执行游标中的SELECT*/
    WHILE  1=1                 --建立循环
    BEGIN                         --循环体开始
      FETCH NEXT FROM C1 INTO @成绩     /*读游标*/
      
      IF @@fetch_status<>0   /*判断提取结束*/
              BREAK  
      IF @成绩 IS NOT NULL
         IF @成绩 >=90 
            SET @优=@优+1
         ELSE IF @成绩 >=80    
            SET @良=@良+1
         ELSE 
            SET @差=@差+1
    END                                     --循环体结束
    CLOSE C1  /*关闭游标*/
    DEALLOCATE C1  /*释放游标*/
    PRINT '优人数'+CAST(@优 AS CHAR(2))+' 良人数'+CAST(@良 AS CHAR(2)) +' 差人数'+CAST(@差  AS CHAR(2))
    GO

    游标语法框架:

    /*定义有关变量*/
    DECLARE 游标名 CURSOR FOR        /*(1)定义游标*/
            SELECT子查询
    OPEN   游标名                     /*(2)打开游标—执行游标中的SELECT*/
    WHILE  1=1                 --建立循环
    BEGIN                         --循环体开始
      /*(3)读游标的一行到变量, 变量的个数类型要与游标中子查询一致  */
      FETCH NEXT FROM 游标名 INTO @变量1@变量2
      IF @@fetch_status<>0   /*判断提取结束*/
              BREAK  
      处理   
    END                              --循环体结束
    CLOSE  游标名      /*(4)关闭游标*/
    DEALLOCATE  游标名       /*释放游标*/

    练习:

    使用游标, 统计输出男生人数,女生人数,年龄>20的人数,年龄<=20的人数。

    CREATE PROCEDURE P2  
    AS
    --定义变量存放男生人数,女生人数,年龄>20的人数,年龄<=20的人数
    --定义变量存放性别,年龄
    DECLARE C1 CURSOR FOR        /*定义游标*/
           SELECT SSEX,SAGE FROM STUDENT
     ......

    DROP PROCEDURE P2  
    GO
    
    CREATE PROCEDURE P2  
    AS
    DECLARE @MC INT,@WC INT,@UP INT,@DOWN INT
    DECLARE @SSEX CHAR(2),@AGE INT
    SELECT @MC=0,@WC=0,@UP=0,@DOWN=0
    DECLARE C1 CURSOR FOR       
    SELECT SSEX,SAGE FROM STUDENT
    OPEN C1     
    WHILE  1=1                 
    BEGIN                         
      FETCH NEXT FROM C1 INTO @SSEX,@AGE  
      
      IF @@fetch_status<>0   
              BREAK  
      IF @SSEX IS NOT NULL
         IF @SSEX ='' 
            SET @MC=@MC+1
         ELSE IF @SSEX=''    
            SET @WC=@WC+1
       IF @AGE IS NOT NULL
         IF @AGE >20
            SET @UP=@UP+1
         ELSE IF @AGE<=20   
            SET @DOWN=@DOWN+1
    END                                 
    CLOSE C1  /*关闭游标*/
    DEALLOCATE C1  /*释放游标*/
    PRINT '男生人数'+CAST(@MC AS CHAR(2))+'女生人数'+CAST(@WC AS CHAR(2)) 
    + '年龄>20的人数'+ CAST(@UP  AS CHAR(2))+ '年龄<=20的人数'+CAST(@DOWN  AS CHAR(2))
    GO

     

    思考题:

    使用游标, 统计每门课的课名,成绩前三名的学生名。
    定义几个游标?什么游标?
    定义什么变量?
    如何处理?

    DROP PROCEDURE P3
    GO
    
    CREATE PROCEDURE P3 
    @CNO INT
    AS
    DECLARE @SNO INT,@SNAME CHAR(20),@SDEPT CHAR(5),@GRADE INT
    DECLARE @COUNT INT
    DECLARE C1 CURSOR FOR      
    SELECT STUDENT.SNO,SNAME,SDEPT,GRADE 
    FROM STUDENT,SC
    WHERE STUDENT.SNO=SC.SNO AND @CNO=SC.CNO
    ORDER BY GRADE DESC
    SET @COUNT=0
    OPEN C1     
    WHILE  1=1                 
    BEGIN                         
      FETCH NEXT FROM C1 INTO @SNO,@SNAME,@SDEPT,@GRADE
      IF @@fetch_status<>0   
          BREAK  
      IF @COUNT=3
          BREAK
      SET @COUNT=@COUNT+1
      PRINT '学号'+CAST(@SNO AS CHAR(10))+'姓名'+@SNAME+ '系名'
      + @SDEPT+ '成绩'+CAST(@GRADE  AS CHAR(5))
    END                                 
    CLOSE C1  
    DEALLOCATE C1  
    GO

    四 SQL-SERVER 触发器

    WHAT IS TRIGGER?

    触发器是一种特殊的存储过程,它不能被显式地调用,
    而是在往表中插入记录、更改记录或者删除记录时,才被自动地调用。

    SQL-SERVER触发器的类型

    对每个表, 可以建立
    DELETE 触发器
    INSERT 触发器
    UPDATE 触发器

    创建触发器的语法:

    CREATE TRIGGER 触发器名
     ON  表名
     FOR [DELETE, INSERT, UPDATE]
     AS 
      T-SQL语句
    GO

    DELETE, INSERT, UPDATE指定触发器的类型

    两个临时表:  INSERTED 和DELETED

    触发器触发时,系统自动在内存中创建两个临时表:   INSERTED和DELETED
    INSERTED 表临时保存了新记录行(插入或更新后的记录行)  
    DELETED 表临时保存了旧记录行(删除或更新前的记录行)
    结构与触发器对应表相同
    触发器执行完成后,自动删除这两个表
    只读,用于检查操作是否满足业务需求

    查看DELETED, INSERTED内容

    编写触发器, 当选课表修改数据时, 显示修改前后的数据


    编写触发器:
        哪个表?
        哪种触发语句?
        修改前的行,修改后的行存放在哪里?

    CREATE TRIGGER trig_SC
        ON  SC                        
    FOR UPDATE    AS         --SC表的UPDATE触发器
          SELECT   * FROM deleted  --deleted存旧数据   
          SELECT * FROM inserted  -- inserted存新数据
    GO 

    UPDATE触发器  

    编写触发器, 使学生的年龄修改只能增1

    编写触发器:
        哪个表?
        哪种触发语句?
        修改前的行,修改后的行存放在哪里?
        修改前的年龄? 修改后的年龄?

    -----使学生的年龄修改只能增1----
    DROP TRIGGER trig_update_sage    --为防止重建时报错, 先删一下
    GO
    CREATE TRIGGER trig_update_sage
    ON STUDENT                        
    FOR UPDATE    AS         --STUDENT表的UPDATE触发器
          DECLARE @beforeSage int,@afterSage int    --定义变量  
          SET @beforeSage=(SELECT TOP 1 SAGE FROM deleted)  --旧数据   
          SET @afterSage=(SELECT TOP 1 SAGE FROM inserted)  -- 新数据
          IF @afterSage-@beforeSage<>1 AND @afterSage-@beforeSage<>0
            BEGIN
                PRINT ‘年龄修改只能增1’     --报错  
                ROLLBACK TRANSACTION --回滚,撤销引起触发器的UPDATE语句
            END
    GO 

    DELETE触发器

    编写触发器, 在deletedsc中记录SC表删除的行 (deletedsc表已建立, 结构同SC)

    编写触发器:
        哪个表?
        哪种触发语句?
        删除的行存放在哪里?

    -------关键代码------
    CREATE TRIGGER trig_delete_SC
     ON SC
      FOR DELETE 
       AS
         INSERT INTO DELETEDSC   SELECT * FROM deleted
     
    GO 

    INSERT触发器---实时统计

    实时统计:在学生表中增加选课门数列CCOUNT和总成绩列GTOTAL
    CREATE TABLE STUDENT
    (SNO  NUMERIC(5)  CONSTRAINT P_STUDENT PRIMARY KEY,
    。。。。。。
            CCOUNT NUMERIC(3),        --选课门数
            GTOTAL NUMERIC(5)          --总成绩
    );
    编写SC的插入、删除和修改触发器, 自动更新学生表中选课门数和总成绩.

    -------关键代码------
    --当插入SC数据时,自动更新学生表中选课门数列和总成绩列.
    CREATE TRIGGER trig_insert_sc
    ON  SC
    FOR insert    AS
          DECLARE @GRADE INT, @SNO INT   
          /* 从INSERTED中取插入的学号和成绩  */
          SELECT   @SNO=SNO,@GRADE=GRADE FROM INSERTED   
          IF @GRADE IS NOT NULL
             UPDATE STUDENT
                 SET CCOUNT=CCOUNT+1,  GTOTAL=GTOTAL+@GRADE
                 WHERE SNO=@SNO    
    GO 

    DELETE触发器 ---实时统计

    DELETE可能删除多行
    要对删除的多行逐行进行处理
    如何进行?

    CREATE TRIGGER trig_delete_sc ON  SC
    FOR DELETE    AS                                 --SC表DELETE触发器
          DECLARE @sno int ,@grade int    --定义变量
          DECLARE C1 CURSOR FOR          --定义游标,存放被删的数据 
               SELECT SNO,GRADE FROM  DELETED
         OPEN C1                                           --打开游标 
         WHILE  1=1                                       --循环
         BEGIN 
             FETCH NEXT FROM C1 INTO  @SNO, @GRADE  --读游标
             IF @@fetch_status<>0                  --如果读完了
                 BREAK  
             IF @GRADE IS NOT NULL
                 UPDATE STUDENT     
    SET CCOUNT=CCOUNT-1,GTOTAL=GTOTAL-@GRADE
    WHERE SNO=@sno END CLOSE C1 DEALLOCATE C1 GO

    当对SC表UPDATE时,如何自动更新学生表中选课门数列和总成绩列?

    对SC表建立UPDATE触发器
    UPDATE可能修改多行
    修改前的数据,修改后的数据?
    要对修改的多行进行处理,如何进行?

    /*建立两个游标C1,C2,分别对应 deleted inserted*/
    /*循环处理游标,发现修改,同步更新STUDENT*/
    DROP TRIGGER trig_update_sc    
    GO
     CREATE TRIGGER trig_update_sc ON SC
     FOR UPDATE AS
     DECLARE @sno1 int,@grade1 int
     DECLARE @sno2 int,@grade2 int
     DECLARE C1 CURSOR FOR
     SELECT SNO,GRADE FROM deleted
     DECLARE C2 CURSOR FOR
     SELECT SNO,GRADE FROM inserted
     OPEN C1
     OPEN C2
     WHILE 1=1
     BEGIN
     FETCH NEXT FROM C1 INTO @SNO1,@GRADE1 
     FETCH NEXT FROM C2 INTO @SNO2,@GRADE2 
     IF @@fetch_status<>0
        BREAK
     
     IF @SNO1=@SNO2/*学号未变*/
     BEGIN
         IF @GRADE1 IS NOT NULL AND @GRADE2 IS NOT NULL AND @GRADE1<>@GRADE2/*更新前后均不为空*/
            UPDATE STUDENT
            SET GTOTAL=GTOTAL-@GRADE1+@GRADE2 
            WHERE SNO=@sno1
         ELSE IF @GRADE1 IS NULL AND @GRADE2 IS NOT NULL/*更新前为空,更新后不为空*/
            UPDATE STUDENT
            SET CCOUNT=CCOUNT+1,
            GTOTAL=GTOTAL+@GRADE2
            WHERE SNO=@sno1
         ELSE IF @GRADE1 IS NOT NULL AND @GRADE2 IS NULL/*更新前不为空,更新后为空*/
            UPDATE STUDENT
            SET CCOUNT=CCOUNT-1,
            GTOTAL=GTOTAL-@GRADE1
            WHERE SNO=@sno1
     END
    
    ELSE/*学号变了*/
    BEGIN
        IF @GRADE1 IS NOT NULL/*对旧学号相当于删选课*/
           UPDATE STUDENT 
           SET CCOUNT=CCOUNT-1,GTOTAL=GTOTAL-@GRADE1 
           WHERE SNO=@sno1
        IF @GRADE2 IS NOT NULL/*对新学号相当于插入选课*/
           UPDATE STUDENT 
           SET CCOUNT=CCOUNT+1,GTOTAL=GTOTAL+@GRADE2 
           WHERE SNO=@sno2
     END
     END/*where*/
     CLOSE C1
     CLOSE C2
     DEALLOCATE C1
     DEALLOCATE C2
     GO

    查看触发器信息

    触发器作为一种特殊的存储过程,在用户创建以后,其名字存放在系统表sysobjects中,其创建源代码存放在syscomments系统表中。
    查看指定表中所定义的触发器及它们的类型:
        EXEC sp_helptrigger  表名
    查看指定触发器的定义文本:
        EXEC sp_helptext  触发器名
    删除触发器:
        DROP TRIGGER   触发器名

    总结

    触发器是在对表进行插入、更新或删除操作时自动执行的存储过程
    触发器作用: 增强数据完整性和安全性,实时统计
    触发器一般都需要使用临时表:deleted表和inserted表,它们存放了被删除或插入的记录行副本
    创建触发器的语法:

     CREATE TRIGGER 触发器名
        ON  表名
        FOR [DELETE, INSERT, UPDATE]
     AS 
        T-SQL语句
     GO
  • 相关阅读:
    服务注册发现Eureka之二:高可用服务注册中心
    可重入锁 公平锁 读写锁、CLH队列、CLH队列锁、自旋锁、排队自旋锁、MCS锁、CLH锁
    红黑树(Red-Black tree)
    fuser 命令小结
    客户端负载均衡Ribbon之三:AvailabilityFilteringRule的坑(Spring Cloud Finchley.SR2)
    mysql重复记录的查询删除方法
    innodb的锁、update单条记录的花费时间压测
    被kill问题之1:进程物理内存远大于Xmx的问题分析
    服务注册发现Eureka之三:Spring Cloud Ribbon实现客户端负载均衡(客户端负载均衡Ribbon之三:使用Ribbon实现客户端的均衡负载)
    十二、jdk工具之jcmd介绍(堆转储、堆分析、获取系统信息、查看堆外内存)
  • 原文地址:https://www.cnblogs.com/wkfvawl/p/10852023.html
Copyright © 2011-2022 走看看