今天幫同事尋找一個函數中的bug。給我的原始碼如下:if exists (select * from dbo.sysobjects where id = object_id(N'[tb_Holiday]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [tb_Holiday]
GO
--定義節假日表
CREATE TABLE tb_Holiday(
HDate smalldatetime primary key clustered, --節假日期
Name nvarchar(50) not null) --假日名稱
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[f_WorkDay]') and xtype in (N'FN', N'IF', N'TF'))
drop function [dbo].[f_WorkDay]
GO
--計算兩個日期之間的工作天數
CREATE FUNCTION f_WorkDay(
@dt_begin datetime, --計算的開始日期
@dt_end datetime --計算的結束日期
)RETURNS int
AS
BEGIN
IF @dt_begin>@dt_end
RETURN(DATEDIFF(Day,@dt_begin,@dt_end)
+1-(
SELECT COUNT(*) FROM tb_Holiday
WHERE HDate BETWEEN @dt_begin AND @dt_end))
RETURN(-(DATEDIFF(Day,@dt_end,@dt_begin)
+1-(
SELECT COUNT(*) FROM tb_Holiday
WHERE HDate BETWEEN @dt_end AND @dt_begin)))
END
GO
執行如下查詢:
select dbo.f_workday('2006-01-01','2006-02-01')
select dbo.f_workday('2006-02-01','2006-01-01')
和理想結果相差懸殊啊。
雖然上本身就有邏輯的錯誤,但主要的問題不在這裡。當時就懷疑實際語句的執行情況是否正確,測試後發現一個奇怪的問題。就是不管在函數還是預存程序中,return 後面加上確切的數字和簡單的算術計算都沒問題,都可以使函數或預存程序立刻返回。但是傳回值中如果包含查詢語句,如:return (select count(*) from TableName),那麼函數或預存程序將繼續執行,如果後面沒有另外的return,外面得到的傳回值倒是還能記得之前那個傳回值(就是return (select count(*) from TableName)這句的傳回值)。百思不得其解,網上隨便查了查,沒找到原因。難道return 後面的運算式不能是一個子查詢?看看有哪位高手知曉其根本原因。