2010年10月2日 星期六

T-SQL 顯示民國年

在 Hunterpo's IT Vision 看到一篇「自訂 SQL Server 日期轉民國年格式函數」文章,Hunterpo 用心製作了一個很完善的 Function,並考慮了各種日期輸出格式。但保哥回了一段要注意,使用Function 可能會影響效能的話,著實讓我想著是否有更簡單的方式可以完成民國年的需求。

後來發現,其實也不需要用到自訂函數這麼華麗,用短短幾行也可以完成。


declare @now datetime
set @now=getdate()

select convert(varchar(3),datepart(year,@now)-1911) 
+right('0'+ convert(varchar(2),datepart(month,@now)),2)
+right('0'+ convert(varchar(2),datepart(day,@now)),2) as ChineseYear

至於使用 Function 是否會影響效能?答案是肯定會的。簡單的比喻,如果你自己撰寫了一個自訂的 Function,假設執行一次要花 0.01 秒,當你有 50000筆資料時,

select  dbo.myFunction(x) from myTable

就會多花 0.01X50000 的時間。然而,這只是簡單推算,實際上你可能會有加上 where 條件,將資料筆數限制在比較少的情況,正因為所篩選的結果資料量不大,同時也就減少了使用 Function 所帶來額外花費時間的衝擊。

然而, 使用 Function 最大的危險,並不在於 select 敘述裡,而是在 where 條件敘述裡。剛剛有提到,如果只是放在 select 敘述裡,花費時間只會因為搜尋後結果資料集的大小而有影響;但如果把他放在 where 條件敘述裡,則很有可能是每一筆資料都要去執行一次你的 Function,甚至破壞您原先建立 Index 的效益。這裡用「有可能」這字眼,代表著,只要你使用正確,還是可以開開心心使用 Function的,這裡所指的 Function,是同時包括使用者自訂 Function 與系統內建的 Function。

建議可以參考「Improving SQL Server Performance」這篇文章,裡面的一小節「Avoid Explicit or Implicit Functions in WHERE Clauses」有個很棒的範例可以說明。如果你在 where 條件敘述句裡,使用了 Function ,且 Function 裡面是用了某個資料欄位當參數,那這就犯了兵家大忌,要打屁股了。

小弟不才,剽竊了原文的程式碼,也不想告知(人家是 msdn 嘛...)。

SELECT OrderID FROM NorthWind.dbo.Orders WHERE DATEADD(day, 15, 
OrderDate) = '07/23/1996'

SELECT OrderID FROM NorthWind.dbo.Orders WHERE OrderDate = DATEADD(day, 
-15, '07/23/1996')

以上兩行指令,結果是一樣的,但第一行指令,他會使用 Index Scan,每筆資料一行一行去比對;而第二行指令,則是使用 Index Seek。這兩種方法,搜尋成本就差了4倍以上。所以,即便你只是使用系統內建的 Function,但還是要注意擺放的時機與位置,避免日後無眠無夜的調校程式。


參考來源:
1.http://www.dotblogs.com.tw/hunterpo/archive/2010/08/15/17208.aspx
2.http://msdn.microsoft.com/en-us/library/ff647793.aspx