• sqlserver存储过程的使用


    参考网址:https://www.cnblogs.com/chaoa/articles/3894311.html(存储过程)

           https://www.cnblogs.com/selene/p/4480328.html(游标)

    --创建学生表
    create table student1(
    id int,
    cardId int,
    name varchar(32),
    birthday datetime,
    sex varchar(32)
    )
    
    1    1    王男    1996-08-27 09:00:00.0002    2    杨幂    1995-04-20 06:00:00.0003    3    程峰    1988-09-17 15:30:00.0004    4    唐嫣    1895-05-27 14:30:28.0005    5    王菲    1990-01-20 19:00:00.0006    6    王忠磊    1980-08-08 08:09:00.000--一、定义变量 参考:[https://www.cnblogs.com/chaoa/articles/3894311.html]
    --简单赋值 
    declare @a int
    set @a=5 
    print @a 
    --SELECT @a
      
    --使用select语句赋值 
    declare @user1 nvarchar(50) 
    select @user1='张三'
    print @user1 
    declare @user2 nvarchar(50) 
    select @user2 = name from student1 where ID=1 
    print @user2 
      
    --使用update语句赋值 
    declare @user3 nvarchar(50) 
    update student1 set @user3 = name where ID=1 
    --print @user3
    SELECT @user3
    
    --二、表、临时表、表变量
    
    --创建临时表1 
    create table #DU_User1 ( 
    id int,
    cardId int,
    name varchar(32),
    birthday datetime,
    sex varchar(32)
    ); 
    
    --向临时表1插入一条记录 
    insert into #DU_User1 (id, cardId, name, birthday, sex) values (11,11,'刘亦菲',GETDATE(),''); 
      
    --从student1查询数据,填充至新生成的临时表(在插入数据的同时创建了临时表) 
    select * into #DU_User2 from student1 where ID<8 
      
    --查询并联合两临时表 
    select * from #DU_User2 where ID<3 union select * from #DU_User1 
      
    --删除两临时表 
    drop table #DU_User1 
    drop table #DU_User2
     
    --创建临时表 
    CREATE TABLE #t( 
    id int,
    cardId int,
    name varchar(32),
    birthday datetime,
    sex varchar(32)
    ) 
      
    --将查询结果集(多条数据)插入临时表 
    insert into #t select * from student1 
    --不能这样插入 
    --select * into #t from student1 
      
    --添加一列,为int型自增长子段 
    alter table #t add [myid] int NOT NULL IDENTITY(1,1) 
    --添加一列,默认填充全球唯一标识 
    alter table #t add [myid1] uniqueidentifier NOT NULL default(newid()) 
      
    select * from #t 
    drop table #t
    
    --给查询结果集增加自增长列 
    --无主键时: 
    select IDENTITY(int,1,1)as ID, cardId, name, birthday, sex  into #t from student1
    select * from #t 
      
    --有主键时: 
    select (select SUM(1) from student1 where ID<= a.ID) as myID,* from student1 a order by myID
    
    --定义表变量 
    declare @t table( 
        id int not null, 
        msg nvarchar(50) null
    ) 
    insert into @t values(1,'1') 
    insert into @t values(2,'2') 
    select * from @t
    
    --三、循环
    
    --while循环计算1到100的和 
    declare @a int
    declare @sum int
    set @a=1 
    set @sum=0 
    while @a<=100 
    begin
        set @sum+=@a 
        set @a+=1 
    end
    print @sum
    
    --四、条件语句
    
    --if,else条件分支 
    if(1+1=2) 
    begin
        print ''
    end
    else
    begin
        print ''
    end
      
    --when then条件分支 
    declare @today int
    declare @week nvarchar(3) 
    set @today=3 
    set @week=case
        when @today=1 then '星期一'
        when @today=2 then '星期二'
        when @today=3 then '星期三'
        when @today=4 then '星期四'
        when @today=5 then '星期五'
        when @today=6 then '星期六'
        when @today=7 then '星期日'
        else '值错误'
    end
    print @week
    
    
    --五、游标 参考[https://www.cnblogs.com/selene/p/4480328.html]
    --如果不指定游标的作用域,默认为global
    (1) 使用游标给变量赋值(最标准)
    declare @id int
    declare @cardId int
    declare @name varchar(50) 
    
    --定义一个游标,并赋值 
    declare user_cur cursor for select id,cardId,name from student1 
    --打开游标 
    open user_cur 
    
    --判断游标是否执行成功
    fetch next from user_cur into @id,@cardId,@name
    while @@fetch_status=0 
    begin
        SELECT @id, @cardId, @name, @@fetch_status
        --读取游标中的数据 fetch用来读取游标中的某一个行数据 next取下一行
        fetch next from user_cur into @id,@cardId,@name        
    end
    --关闭游标
    close user_cur 
    --摧毁游标(释放游标)
    deallocate user_cur
    
    eg1: 使用游标求和
    ALTER PROCEDURE [dbo].[ss_1]
    AS
    BEGIN
        DECLARE @zj int = 0;
        DECLARE @name VARCHAR(100) = '';
        DECLARE @sal int = 0;
        
        declare cur_js cursor for SELECT name, sal FROM student2
        open cur_js  
        fetch cur_js into @name, @sal
        while @@fetch_status=0 
            BEGIN
                if @sal > 50
                SET @zj = @sal + @zj
                fetch cur_js into @name, @sal
            END
        close cur_js  
        deallocate cur_js 
        SELECT @name as '姓名', @zj AS '总工资'
    END
    
    
    
    (2) 使用游标变量
    
    --声明变量用DECLARE,为变量赋值可以用set或SELECT语句,对于游标变量的声明和赋值,
    --其操作基本相同。在具体使用时,首先要创建一个游标,将其打开后,将游标的值赋给游
    --标变量,并通过FETCH语句从游标变量中读取值,最后关闭释放游标。
    eg:
    --声明游标变量
    declare @var_cur Cursor 
    --创建游标 
    declare user_cur cursor for select id,cardId,name from student1 
    --打开游标 
    open user_cur 
    --为游标变量赋值
    set @var_cur = user_cur
    --从游标变量中读取值
    fetch next from @var_cur
    --判断fetch语句是否执行成功
    while @@fetch_status=0 
    begin
        fetch next from @var_cur
    end
    --关闭游标
    close user_cur 
    --释放游标
    deallocate user_cur
    
    (3)用游标为变量赋值
    
    --在游标的操作过程中,可以使用FETCH语句将数据值存入变量,
    --这些保持表中列值的变量可以在后面的程序中使用
    declare @id int
    declare @ucardId int
    declare @uname varchar(50) 
    
    --定义一个游标,并赋值 
    declare user_cur cursor for select id,cardId,name from student1 WHERE id = 2
    --打开游标 
    open user_cur 
    
    --判断游标是否执行成功
    fetch next from user_cur into @id,@ucardId,@uname 
    print 'id 学号 姓名'
    while @@fetch_status=0 
    begin
        print @uname
        fetch next from user_cur into @id,@ucardId,@uname 
    end
    --关闭游标
    close user_cur 
    --摧毁游标(释放游标)
    deallocate user_cur
    
    (4)用ORDER BY 子句改变游标中的执行顺序
    
    游标是一个查询结果集,那么能不能对结果进行排序呢?答案是否定的。与基本的SELECT
    语句中的排序方法相同,ORDER BY子句添加到查询中可以对游标查询的结果排序。
    注意:只有出现在游标中的SELECT语句中的列才能作为ORDER BY 子句的排序列,而对与非
    游标的SELECT语句中,表中任何列都可以作为ORDER BY 的排序列,即使该列没有出现在SELECT语句的查询结果列中.
    --定义一个游标,并赋值 
    declare user_cur cursor for select id,cardId,name from student1 ORDER BY id DESC
    --打开游标 
    open user_cur 
    
    --判断游标是否执行成功
    fetch next from user_cur
    while @@fetch_status=0 
    begin
        --读取游标中的数据 fetch用来读取游标中的某一个行数据 next取下一行
        fetch next from user_cur
    end
    --关闭游标
    close user_cur 
    --摧毁游标(释放游标)
    deallocate user_cur
    
    (5)用游标修改数据
    --修改id等于@sid处name字段的值
    declare @id int
    declare @sid int = 1
    
    --定义一个游标,并赋值 
    declare user_cur cursor for select id from student1
    --打开游标 
    open user_cur 
    --判断游标是否执行成功
    fetch next from user_cur into @id
    while @@fetch_status=0 
    begin
        if @id = @sid
        begin 
            --修改表中字段的值
            update student1 set name = '王楠' where id = @sid
        end
        fetch next from user_cur into @id
    end
    --关闭游标
    close user_cur 
    --摧毁游标(释放游标)
    deallocate user_cur
    
    SELECT * FROM student1
    
    (6)用游标删除数据
    
    使用游标删除数据时,既可以删除游标结果集中的数据,也可以删除基本表中的数据.
    declare @id int
    declare @sid int = 1
    
    --定义一个游标,并赋值 
    declare user_cur cursor for select id from student1
    --打开游标 
    open user_cur 
    
    --判断游标是否执行成功
    fetch next from user_cur into @id
    while @@fetch_status=0 
    begin
        if @id = @sid
        begin 
            --删除表中的值
            delete from student1 where id = @sid
        end
        fetch next from user_cur into @id
    end
    --关闭游标
    close user_cur 
    --摧毁游标(释放游标)
    deallocate user_cur
    
    SELECT * FROM student1
    
    --六、触发器
    
    --触发器中的临时表:
    --Inserted:存放进行insert和update 操作后的数据 
    --Deleted:存放进行delete 和update操作前的数据   
      
    --创建触发器 
    Create trigger User_OnUpdate  
        On student1  
        for Update 
    As 
        declare @msg nvarchar(50) 
        --@msg记录修改情况 
        select @msg = N'姓名从“' + Deleted.Name + N'”修改为“' + Inserted.Name + '' from Inserted,Deleted 
        --插入日志表 
        insert into [LOG](MSG)values(@msg) 
          
    --删除触发器 
    drop trigger User_OnUpdate
    
    --七、存储过程
    
    --创建带output参数的存储过程 
    CREATE PROCEDURE PR_Sum 
        @a int, 
        @b int, 
        @sum int output
    AS
    BEGIN
        set @sum=@a+@b 
    END
      
    --创建Return返回值存储过程 
    CREATE PROCEDURE PR_Sum2 
        @a int, 
        @b int
    AS
    BEGIN
        Return @a+@b 
    END
          
    --执行存储过程获取output型返回值 
    declare @mysum int
    execute PR_Sum 1,2,@mysum output
    print @mysum 
      
    --执行存储过程获取Return型返回值 
    declare @mysum2 int
    execute @mysum2= PR_Sum2 1,2 
    print @mysum2
     
    --八、自定义函数
    
      函数的分类:
    
        1)标量值函数
    
        2)表值函数
    
            a:内联表值函数
    
            b:多语句表值函数
    
        3)系统函数
    
      
    
    --新建标量值函数 
    create function FUNC_Sum1 
    ( 
        @a int, 
        @b int
    ) 
    returns int
    as
    begin
        return @a+@b 
    end
      
    --新建内联表值函数 
    create function FUNC_UserTab_1 
    ( 
        @myId int
    ) 
    returns table
    as
    return (select * from ST_User where ID<@myId) 
      
    --新建多语句表值函数 
    create function FUNC_UserTab_2 
    ( 
        @myId int
    ) 
    returns @t table
    ( 
        [ID] [int] NOT NULL, 
        [Oid] [int] NOT NULL, 
        [Login] [nvarchar](50) NOT NULL, 
        [Rtx] [nvarchar](4) NOT NULL, 
        [Name] [nvarchar](5) NOT NULL, 
        [Password] [nvarchar](max) NULL, 
        [State] [nvarchar](8) NOT NULL
    ) 
    as
    begin
        insert into @t select * from ST_User where ID<@myId 
        return
    end
      
    --调用表值函数 
    select * from dbo.FUNC_UserTab_1(15) 
    --调用标量值函数 
    declare @s int
    set @s=dbo.FUNC_Sum1(100,50) 
    print @s 
      
    --删除标量值函数 
    drop function FUNC_Sum1
    谈谈自定义函数与存储过程的区别:
    
    一、自定义函数:
    
      1. 可以返回表变量
    
      2. 限制颇多,包括
    
        不能使用output参数;
    
        不能用临时表;
    
        函数内部的操作不能影响到外部环境;
    
        不能通过select返回结果集;
    
        不能update,delete,数据库表;
    
      3. 必须return 一个标量值或表变量
    
      自定义函数一般用在复用度高,功能简单单一,争对性强的地方。
    
    二、存储过程
    
      1. 不能返回表变量
    
      2. 限制少,可以执行对数据库表的操作,可以返回数据集
    
      3. 可以return一个标量值,也可以省略return
    
       存储过程一般用在实现复杂的功能,数据操纵方面。
    复制代码
  • 相关阅读:
    Robin Hood CodeForces
    Arthur and Questions CodeForces
    AC日记——过河卒 洛谷 1002
    加密(模拟)
    AC日记——codevs 1086 栈 (卡特兰数)
    AC日记——搞笑世界杯 codevs 1060(dp)
    AC日记—— codevs 1031 质数环(搜索)
    AC日记——产生数 codevs 1009 (弗洛伊德)(组合数学)
    AC日记——阶乘之和 洛谷 P1009(高精度)
    AC日记——逃跑的拉尔夫 codevs 1026 (搜索)
  • 原文地址:https://www.cnblogs.com/shiyun32/p/10297975.html
Copyright © 2020-2023  润新知