对于第二个示例,您可以这样做:
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
(In fact in SQL Server 2012 you can also use FORMAT() so that you don't have to memorize the style numbers, but since I don't know what version you're using I'll leave that for another day.)
All that said, other than saving a few keystrokes in your queries, this encapsulation is actually going to make your queries perform worse (depending on where they are used). For simple conversions like this it is much better to just perform them inline in most cases.