對於你能做到這一點的第二個例子:
CREATE FUNCTION dbo.ConvertDate(@d CHAR(10))
RETURNS DATE
AS
BEGIN
RETURN (SELECT CONVERT(DATE, @d));
END
GO
但更靈活的方法可能是:
CREATE FUNCTION dbo.ConvertRegional
(
@d CHAR(10),
@style TINYINT
)
RETURNS CHAR(10)
AS
BEGIN
RETURN (SELECT CONVERT(CHAR(10), CONVERT(DATE, @d), @style));
END
GO
DECLARE @d CHAR(10);
SELECT @d = '20120428';
SELECT
dbo.ConvertDate(@d),
dbo.ConvertRegional(@d, 101),
dbo.ConvertRegional(@d, 103),
dbo.ConvertRegional(@d, 120);
結果:
---------- ---------- ---------- ----------
2012-04-28 04/28/2012 28/04/2012 2012-04-28
如果你不想要繼續從你的源表中過濾掉壞的非日期(保持WHERE子句中的ISDATE()應該防止函數必須處理這些行),你可以通過這種方式改變函數以避免錯誤,如果NULL是可以的作爲替補:
CREATE FUNCTION dbo.ConvertRegional
(
@d CHAR(10),
@style TINYINT
)
RETURNS CHAR(10)
AS
BEGIN
RETURN (SELECT CASE WHEN ISDATE(@d) = 1 THEN
CONVERT(CHAR(10), CONVERT(DATE, @d), @style)
END);
END
GO
在SQL Server 2012中,你可以做到這一點,而不是,它做同樣的事情,而無需編寫自己的CASE:
CREATE FUNCTION dbo.ConvertRegional
(
@d CHAR(10),
@style TINYINT
)
RETURNS CHAR(10)
AS
BEGIN
RETURN (SELECT CONVERT(CHAR(10), TRY_CONVERT(DATE, @d), @style));
END
GO
(事實上,在SQL Server 2012中你也可以使用FORMAT(),這樣你就不必記住樣式數字,但是因爲我不知道你使用的是什麼版本,所以我會在另一天離開。)
所有這一切,除了在查詢中保存一些擊鍵,這個封裝實際上會讓你的查詢性能變差(取決於它們在哪裏使用)。對於像這樣的簡單轉換,在大多數情況下直接執行它們會更好。
其實你的第一個例子使用103導致28/04/2012不是2012年4月28日。 – 2012-04-29 03:15:33
錯誤:應該是101 – Asynchronous 2012-04-29 03:19:58
請注意,如果您使用的是SQL Server 2012之前的版本,則篩選子句可能會在select子句之前被評估,也可能不會被評估。請參閱@ AaronBertrand對我[問題]的極好迴應(http://dba.stackexchange.com/questions/5312/conversion-of-varchar-data-to-datetime-failing) – billinkc 2012-04-29 12:42:46