Sqlserver存储过程—----传递数组、使用循环
 
Sqlserver 存储过程 数组 循环

背景:

前一段时间做过一个公司内部的员工项目管理系统,其间有个sqlserver存储过程是要从excel文件中读取员工的项目信息,并从db中找出相关的的其他信息插入到一张员工表中。这里涉及两个难点:怎么向存储过程传递多条记录?在存储过程中怎么对这些记录一条条循环处理。

解决方案:

1.      怎么将excel中数据传入到存储过程中?

存储过程是没有办法接受数组参数的,我的做法是先把excel中的信息导入到一张全局的临时表中,在把临时表的表名传递给存储过程,在存储过程中使用临时表内容。

2.      怎么在存储过程中做循环处理?

在存储过程中新建一张临时表,将传递过来的全局临时表的信息保存在该表中,并且在表中添加一个id列,对记录从一开始计数。使用count函数计算记录的个数,使用while语句对id从1到count进行循环

代码:

 1.创建临时表:

IF OBJECT_ID('dbo.create_tempTable') IS NOT NULL 

     DROP PROC dbo.create_tempTable; 

 GO 

 CREATE PROC dbo.create_tempTable     

 AS   

     CREATE TABLE ##tempexcel( 

         pjid char(6),--项目id 

         userid char(6),--用户id 

         PRIMARY KEY(pjid, userid) 

     )


GO

2.具体操作的存储过程:

IF OBJECT_ID('dbo.Staff_insert') IS NOT NULL 

     DROP PROC dbo.Staff_insert; 

 GO 

 CREATE PROC dbo.Staff_insert 

     @temptableName nvarchar(20)--临时表名 

 AS 

 BEGIN 

     --用于实现循环的临时表,intID列用于从1开始对记录计数 

     CREATE TABLE #excelData(intID int identity(1,1),pjid char(6),userid char(6)); 

     --将全局临时表中的数据插入到临时表中 

     INSERT INTO #excelData(pjid,userid) EXEC('SELECT pjid, userid FROM '+ @temptableName); 

     --计算记录的个数 

     SELECT @count= COUNT(1) FROM #excelData; 

     --如果记录存在,进入循环 

     IF(@count > 0) 

     BEGIN 

         SET @i = 1;--循环变量                

         WHILE(@i <= @count) 

         BEGIN 

             -- 根据intid取出要操作的记录 

             SELECT @pjid=pjid,@userid=userid FROM #excelData WHERE intID = @i; 

             --其他操作 

             -- 

             -- 

         END 

     END 

 END




想把一个数据表里的某个字段筛选出来然后,循环的把值传给另一个存储过程,选择使用了临时表。
SQL代码如下:

CREATE TABLE #Temp_TABLE 

 ( 

 ID INT IDENTITY(1,1), 

 TRANSID VARCHAR(30), --出库单号 

 PRIMARY KEY (ID) 

 ) 

 INSERT INTO #Temp_TABLE 

 SELECT TRANSID FROM A WHERE A.RPID='RP00913031200001'--从A表取出符合条件的数据插入到临时表 

 DECLARE @TOTAL_COUNT INT,--临时表记录条数 

 @NOW_COUNT INT,--现在遍历到哪条记录 

 @TRID VARCHAR(30)--当前遍历的transid 

 SELECT @TOTAL_COUNT=COUNT(*) FROM #Temp_TABLE 

 SET @NOW_COUNT=1; 

 WHILE(@NOW_COUNT<=@TOTAL_COUNT) 

  BEGIN 

    SELECT @TRID=TRANSID FROM #Temp_TABLE 

    WHERE ID=@NOW_COUNT --关键就在这(一切都因这个地方而不一样了哦) 

    EXEC proc_monprocess @TRID--传给另一个存储过程 

    SET @NOW_COUNT=@NOW_COUNT+1 

  END 

 DROP TABLE #Temp_TABLE 


 有关表的数据插入 

 1、把临时表中的数据插入到另一个表中 

 insert into 表 select * from #temp 

 2、把一个表中字段复制到临时表中 

 select * into #temp from   表 where ... 

 3、本地临时表的名称以单个数字符号 (#) 打头;它们仅对当前的用户连接是可见的; 

 4、当用户从 SQL Server 实例断开连接时被删除。 

 5、判断临时表是否存在 

 create proc temp(@tablename varchar(200)) 

 as 

 begin 

 declare @exec varchar(8000) 

 set @exec='use tempdb 

 if exists(select * from sysobjects 

 where id=object_id(''tempdb..'+@tablename+''')) 

 select ''存在'' 

 else 

 select ''不存在''' 

 exec (@exec) 

 end 



--计算一段时间内工作的天数
 select dbo.f_workday('2014-06-01','2014-07-30')

 create function  f_workday(
 -- 参数
 @date_begin datetime, --计算开始日期
 @date_end datetime )  --计算结束日期
 returns int  -- 返回值数据类型

 as
 begin

     declare  @weeks  int,  -- 声明变量
              @workday int
 -- SQL语句(必须有return 变量或值)
 ---计算整周的工作天数
   select  @weeks=(datediff (day ,@date_begin, @date_end)+1)/7,     -- 计算开始和结束日期的之间的周数(完整的周)
           @workday=@weeks*5,                                       --整周的工作天数----
           @date_begin=dateadd(day,@weeks*7,@date_begin)            --最後一个不完整的周的工作天数
     while  @date_begin<=@date_end
     begin 
        select @workday = case when (@@datefirst+datepart(weekday,@date_begin)-1)%7 between 1 and 5 then @workday+1
        else @workday+1 end, @date_begin =@date_begin+1
     end
 return (@workday)

 end

 demo2:
  -- 根据 questionID  查询 pName
 create FUNCTION [dbo].[getPointNameByQuestionID](@questionID INT)
 RETURNs varchar(256)
 AS
 BEGIN
     DECLARE @pName VARCHAR(256)

     SELECT DISTINCT TOP 1 @pName = p.pointName    
     FROM EXPORT_POINT_QUESTION_DHY pq 
         LEFT JOIN QZ_POINT p ON pq.pointID = p.pointID
     WHERE pq.questionID = @questionID

     RETURN ISNULL(@pName , '其他' )
 END
 GO

 select dbo.getPointNameByQuestionID(123);

 demo3:

 -----比较两个值大小,返回小的----
 create FUNCTION [dbo].[getMin]
 (
     @num1 int,
     @num2 int
 )
 RETURNS int
 as 
 BEGIN
     declare @num int
     if @num1>@num2
     begin
         set @num=@num2
     end
     else 
     begin
         set @num=@num1
     end
     return @num
 END
 GO