1. 程式人生 > >關於SQL SERVER 儲存過程使用(2)

關於SQL SERVER 儲存過程使用(2)

  現在有一場景,需要調用出公司員工在本週的請假天數。程式碼如下(1),本人一開始寫的時候用遍歷裡面套著一個遍歷,發現效果出不來如下(2),求是否有什麼方法可以實現遍歷裡面還有個遍歷。

SQL程式碼(1):

--建立儲存過程
create procedure LeaveTimes
--接收傳入值  使用者名稱  當前日期
@UserNames nvarchar(60),        --接收的iwork使用者名稱
@CurrentTime datetime,           --接收的當前日期,即為登入iwork的校驗系統時間
@LeaveDay decimal(4,1)=0 output             --輸出請假天數   

as 
begin
	--傳入的值不能為空
	IF(
	@UserNames IS NOT NULL AND @UserNames <> '' 
	AND
	@CurrentTime IS NOT NULL AND @CurrentTime <> ''
	)

	begin
		--查出當前日期對應的週一與週日日期
	    DECLARE @Mondaytime DATETIME;   ---本週的週一日期
		DECLARE @Sundaytime DATETIME;    ---本週的週日日期
		set @Mondaytime = DATEADD(week,DATEDIFF(week,0,@CurrentTime),0)
		set @Sundaytime =  DATEADD(week,DATEDIFF(week,0,@CurrentTime),6)

		--建立一個臨時表,用於儲存是否為工作日資料
		create table #T(DDay datetime,Whether int)
		insert into #T(DDay,Whether)
		--呼叫OAWorkTime儲存過程,獲取這周工作日為哪幾天
		exec OAWorkTime @Mondaytime,@Sundaytime
		delete from #T where Whether <> 0

		
		--申明一個表變數用於存使用者請假資訊
		declare @Temp table
		(
		ID varchar(60),
		vastartdate datetime,
		vaenddate  datetime,
		numday  decimal(4,1)
		);
		--將此使用者的所有請假資訊插入到表變數中
		insert into @Temp(ID,vastartdate,vaenddate,numday)
		select 
		b.field0023,b.field0025,b.field0026,b.field0027 
		from
		formmain_6113 a,formson_6116 b 
		where a.ID=b.formmain_id  
		and  dbo.getName(a.field0001)= @UserNames
	

		--申明一個表變數為總表用於後續可以遍歷
		declare @CountTemp table
		(
		IID int identity(1,1), 
		ID varchar(60),
		vastartdate datetime,
		vaenddate  datetime,
		numday  decimal(4,1),
		DDay datetime,
		Whether int
		);
		--將請假資訊、工作日資訊做錶鏈接放在同一張表上
		insert into @CountTemp(ID,vastartdate,vaenddate,numday,DDay,Whether)
		select 
		a.ID,a.vastartdate,a.vaenddate,a.numday,b.DDay,b.Whether
		FROM
		@Temp as a,#T as b 

		--定義總表中的每個欄位
		declare
			@IID int,   --唯一值
			@ID varchar(60),
			@vastartdate datetime,
			@vaenddate datetime,
			@numday decimal(4,1),
			@DDay datetime,
			@Whether int;

		--定義之後判斷請假中小時使用
		DECLARE @vastartdate11 DATETIME;
		DECLARE @vaenddate11 DATETIME;  

		WHILE exists (select IID  from @CountTemp)
		BEGIN
			set rowcount 1
			--將第一行的資料賦值給@變數中
			select 
			@IID=IID,@ID=ID,@vastartdate=vastartdate,@vaenddate=vaenddate,@numday=numday,
			@DDay=DDay,@Whether=Whether 
			from
			@CountTemp;
			
			set @vastartdate11 = @vastartdate
			set @vaenddate11 = @vaenddate
			set @DDay = convert(date,convert(varchar(60),@DDay,111))
			set @vastartdate =  convert(date,convert(varchar(60),@vastartdate,111))
			set @vaenddate =  convert(date,convert(varchar(60),@vaenddate,111))
			
			--刪除掉總表中當前工作日不在請假日期範圍內部的值
			delete from @CountTemp where @DDay NOT BETWEEN @vastartdate AND @vaenddate
			
			--請假的幾種情況
			--1、請假開始時間、結束時間都在當天工作日
			if @DDay = @vastartdate and @DDay = @vaenddate
			begin
				set @LeaveDay = @LeaveDay + @numday
			end
			--2、請假開始時間是今天工作日,結束時間在後邊
			if @DDay = @vastartdate  and   @DDay < @vaenddate
			begin
				if DATEPART(hh,@vastartdate11) < 12 
				begin
					set @LeaveDay = @LeaveDay + 1
				end
				else
				begin
					set @LeaveDay = @LeaveDay + 0.5
				end
			end
			--3、請假開始時間在之前,結束時間在今天工作日
			if @DDay > @vastartdate  and   @DDay = @vaenddate
			begin
				if DATEPART(hh,@vaenddate11)< 15
				begin
					set @LeaveDay = @LeaveDay + 0.5
				end
				else
				begin
					set @LeaveDay = @LeaveDay + 1
				end
			end
			--4、請假時間在之後,結束時間在之前,在中間
			if 	@DDay > @vastartdate  and   @DDay < @vaenddate
			begin
				set @LeaveDay = @LeaveDay + 1
			end	

			set rowcount 0
			delete from @CountTemp where 
[email protected]
END --待不使用了之後刪除臨時表資料並刪除臨時表 truncate table #T drop table #T BEGIN select @LeaveDay AS 請假天數 END END END --execute LeaveTimes '俞豔','2018-01-19 13:30' --execute LeaveTimes '尹欣瑋','2018-05-16 09:30' --DROP PROCEDURE LeaveTimes

SQL程式碼(2):是否有別的方法實現下面的效果呢?

		--此為迴圈使用者請假資訊
		while exists(select ID from @Temp)
		-- 開始遍歷請假每行資料
		begin
			set rowcount 1
			-- 將第一行的資料賦值給@變數中
			select @ID=ID,@vastartdate=vastartdate,@vaenddate=vaenddate,@numday=numday from @Temp;
			
			select @ID,@vastartdate,@vaenddate,@numday from @Temp

			if  exists(select ID from @Temp)
			BEGIN
				--此為是否為工作日遍歷
				while exists(select DDay from #T)
				BEGIN
					SET rowcount 1
					select @DDay =DDay,@Whether=Whether from #T;

					select @DDay,@Whether FROM #T

					--請假的無種情況
					--1、請假開始時間、結束時間都在當天工作日
					if @DDay = @vastartdate and @DDay = @vaenddate
					begin
						set @LeaveDay = @LeaveDay + @numday
					end
					--2、請假開始時間是今天工作日,結束時間在後邊
					if @DDay = @vastartdate  and   @DDay <= @vaenddate
					begin
						if DATEPART(hh,@DDay) < 12 
						begin
							set @LeaveDay = @LeaveDay + 1
						end
						else
						begin
							set @LeaveDay = @LeaveDay + 0.5
						end
					end
					--3、請假開始時間在之前,結束時間在今天工作日
					if @DDay > @vastartdate  and   @DDay = @vaenddate
					begin
						if DATEPART(hh,@DDay)< 15
						begin
							set @LeaveDay = @LeaveDay + 1
						end
						else
						begin
							set @LeaveDay = @LeaveDay + 0.5
						end
					end
					--4、請假時間在之後,結束時間在之前,在中間
					if 	@DDay < @vastartdate  and   @DDay > @vaenddate
					begin
						set @LeaveDay = @LeaveDay + 1
					end
					
					set rowcount 0
					delete from #T where 
[email protected]
END END