zoukankan      html  css  js  c++  java
  • 步步为营-51-存储过程

    说明 :存储过程类比C#中的方法

    1.1 语法:create procedure 存储过程名称

    @变量 类型[=默认值] [output],

    @变量 类型[=默认值] [output] ,

    ...

    as

    begin

      内容

    end

    1.2 创建一个数据表,并添加数据

    use DemoDB
    create table bank 
    (
        cId char(4) primary key not null,
        balance money 
    )
    insert  into bank (cId,balance) Values('0001',1000);
    insert  into bank (cId,balance) Values('0002',10);
    select  * from bank;
    View Code

    1.3 创建存储过程
      1.3.1 存储过程Version:1.0

    --02  创建存储过程 ------
    go
    create procedure usp_转账_01
    as
    begin
        --02-01 捕获异常
        begin try
            --02-02 事务通过事务比较好
            begin transaction
                Update bank set balance = balance - 200 where cId = '0001'
                Update bank set balance = balance + 200 where cId = '0002'
            commit transaction
        end try
         
        BEGIN catch
            rollback transaction
        END catch
    end
    
    --03 执行存储过程---
    exec usp_转账_01;
    1.0

      1.3.2 存储过程1.0没有办法指定某个账号及金额,而且也不知道是否转账成功.所以对其进行升级

        1.3.3 添加约束  alter table bank add constraint CK_bank_balance check(balance>0 );    

      
    --02  创建存储过程 ------
    go
    create procedure usp_转账_02
    @from Char(4),
    @to char(4),
    @money money,
    @IsSuccess nvarchar(32) output 
    as
    begin
        --02-01 捕获异常
        begin try
            --02-02 事务通过事务比较好
            begin transaction
                Update bank set balance = balance - @money where cId = @from
                Update bank set balance = balance + @money where cId = @to
            commit transaction
            set @IsSuccess = '转账成功!'
        end try     
        BEGIN catch
            rollback transaction
            set @IsSuccess = '转账失败!'
        END catch
    end
    View Code
      
        --03-01 按顺序输入参数
        declare @IsSuccess nvarchar(32)
       exec usp_转账_02 '0001','0002',100, @IsSuccess output;
       select @IsSuccess
           --03-02 按指定内容输入参数
        declare @IsSuccess nvarchar(32)
       exec usp_转账_02 @from='0001',@to='0002',@money=100, @IsSuccess= @IsSuccess output;
       select @IsSuccess
    执行存储过程

    运行结果

    执行成功后

    再次执行,由于约束限制,执行失败

    2.1 存储过程在C#中的调用  

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Data.SqlClient;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace ProcedureDemo
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void btnConfirm_Click(object sender, EventArgs e)
            {
                string connStr = "server=.;uid=sa;pwd =sa;database=DemoDB";
                string from = txtFrom.Text;
                string to = txtTo.Text;
                string money = txtMoney.Text;
                using (SqlConnection conn = new SqlConnection( connStr))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand())
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Connection = conn;
    
                        //01 将SQLcommand的text文本设置成存储过程的名称
                        cmd.CommandText = "usp_转账_02";
                        //02 设置参数
                        SqlParameter[] sps =
                        {
                            new SqlParameter("@from",from), 
                            new SqlParameter("@to",to), 
                            new SqlParameter("@money",money),
                            //传出参数
                            new SqlParameter("@IsSuccess",SqlDbType.NVarChar,32), 
                        };
                        //指明输出参数
                        sps[3].Direction = ParameterDirection.Output;
                        //03执行SQL语句,所选择的方法根据存储过程的返回值而定,
                        cmd.Parameters.AddRange(sps);
    
                        cmd.ExecuteNonQuery();
    
                        MessageBox.Show(sps[3].Value.ToString());
                    }
                }
    
            }
        }
    }
    C#代码

    运行效果

    3.1 job任务用到的存储过程,

      场景:一张表中存储一个ProcessID和StrSQL语句,每隔一段时间遍历该表进行更新另一张(权限表)

          3.1.1 第一步,先实现传入对应的ProcessID和StrSQL实现更新

    ALTER procedure [dbo].[sp_UpdateProcRightsStartUserForJob2]
      
      @ProcID Int,
     @StrSQL varchar(max)
    
    as
    begin
     
       
     BEGIN
         
         delete from ProcRightsStartUser where ProcID = @ProcID
          IF OBJECT_ID('tempdb.dbo.#tbl_UserID_Temp','U') IS NOT NULL DROP TABLE dbo.#tbl_UserID_Temp;
         CREATE TABLE #tbl_UserID_Temp (ProcID int,UserID varchar(50) )   --创建一个临时表
         INSERT INTO #tbl_UserID_Temp(UserID) EXEC (@StrSQL)              --StrSQL语句可能获得多行单列数据
         Update #tbl_UserID_Temp set ProcID=@ProcID;
         INSERT INTO ProcRightsStartUser(ProcID,UserID)  select ProcID,UserID from #tbl_UserID_Temp 
         
     END
     
     
              
        
        
    end
    View Code

      3.1.2 进一步完善

    ALTER procedure [dbo].[sp_UpdateProcRightsStartUserForJob]
      
    as
    begin 
      --01 捕获异常
      begin try
            -- 创建临时表
         IF OBJECT_ID('tempdb.dbo.#devicetemp','U') IS NOT NULL DROP TABLE dbo.#devicetemp; 
         SELECT ProcessID,StrSQL 
         INTO dbo.#devicetemp
        from ProcRightsStartPermission 
         ORDER BY ProcessID;
         -- 声明变量
         DECLARE
             @ProcessID AS INT,
             @StrSQL varchar(max)  
             
         WHILE EXISTS(SELECT ProcessID FROM dbo.#devicetemp)
         BEGIN
             -- 也可以使用top 1
             --SET ROWCOUNT 1
             SELECT @ProcessID=ProcessID, @StrSQL=StrSQL  FROM dbo.#devicetemp;
                    --print @StrSQL
                begin transaction           
                delete from ProcRightsStartUser where ProcessID = @ProcessID
                 IF OBJECT_ID('tempdb.dbo.#tbl_UserID_Temp','U') IS NOT NULL DROP TABLE dbo.#tbl_UserID_Temp;
                CREATE TABLE #tbl_UserID_Temp (ProcessID int,UserID varchar(50) )
                INSERT INTO #tbl_UserID_Temp(UserID)EXEC (@StrSQL)         
                Update #tbl_UserID_Temp set ProcessID=@ProcessID;
                INSERT INTO ProcRightsStartUser(ProcessID,UserID)  select ProcessID,UserID from #tbl_UserID_Temp 
                commit transaction                         
             SET ROWCOUNT 0
             
             DELETE FROM dbo.#devicetemp WHERE ProcessID=@ProcessID;
         END 
        end try     
        BEGIN catch
            rollback transaction
           -- set @IsSuccess = '失败!'
        END catch
    end
    View Code

    3.2 分割字符串进行循环

    ALTER procedure [dbo].[sp_UpdateProcRightsStartUser]
     @ProcID Int,
     @UsersID nvarchar(max) --权宜之计
    as
    begin
        --02-01 捕获异常
        begin try
            --02-02 事务通过事务比较好,如果  1删除数据,2插入数据,  如果插入失败那么也不能删除
            begin transaction
                delete from ProcRightsStartUser where ProcID = @ProcID
                --02-03 按照";"分割字符串
                Begin
                    Declare @i Int
                    Set @UsersID = RTrim(LTrim(@UsersID))          --去掉字符串变量左右空白
                    Set @i = CharIndex(';',@UsersID)             --获取第一个分隔字符所在字符中的索引位置@i
                    While @i >= 1                           --while循环,一直到@i=0结束,因为索引为0的话说明字符串中已不存在分隔符
                    Begin
                        Insert into ProcRightsStartUser (ProcID,UserID) Values(@ProcID,Left(@UsersID,@i-1))
                        Set @UsersID = SubString(@UsersID,@i+1,Len(@UsersID)-@i)
                        Set @i = CharIndex(';',@UsersID)
                    End
                    If @UsersID <> ''
                    Insert into ProcRightsStartUser (ProcID,UserID) Values(@ProcID,@UsersID)
                    --Return
                End         
            commit transaction
           -- set @IsSuccess = '成功!'
        end try     
        BEGIN catch
            rollback transaction
           -- set @IsSuccess = '失败!'
        END catch
    end
    View Code
  • 相关阅读:
    常用排序算法
    多线程基础知识 转
    转 大型项目架构演进过程
    TCP/IP 思维导图
    Java8 List字符串 去重
    docker lnmp php
    jpa 批量插入
    备忘提醒
    IntelliJ IDEA像Eclipse一样打开多个项目(转)
    IntelliJ Idea 常用快捷键列表
  • 原文地址:https://www.cnblogs.com/YK2012/p/6820269.html
Copyright © 2011-2022 走看看