在SQL Server中,我需要用另一个函数包装DATEADD
内置函数。
问题是我需要实现这种行为:
返回类型
返回数据类型是日期参数[...]
的数据类型
例如,如果我传入datetime
作为参数,DATEADD
会返回datetime
。如果我传入date
,DATEADD
会返回date
。
以下示例始终返回datetime
...
create function add_months(@dt date, @interval int)
returns datetime
as
begin
return DATEADD(month, @interval, @dt)
end
如何在SQL Server中实现它?
的(编辑) 的
上下文
我正在执行从informix到SQL Server的数据库迁移。这里的数据库部分不是问题,代码是。我们有数百个程序必须更改,因为它们中嵌入了SQL查询。这是我试图避免使用DATEADD(MONTH, 1, foo)
的主要原因。这种自动转换虽然在大多数情况下很简单,但在某些情况下可能非常困难。使用udf,我可以替换informix函数的名称,而不是进行更深入的重构。
答案 0 :(得分:3)
无法重载功能。我试图想出一种方法来SQL_VARIANT
,但我能想到的所有选择都会导致不必要的令人作呕的并发症。我会创建一个接受并返回date的函数,以及一个接受并返回datetime的函数,并调用相应的函数。精度较低的可以调用较高的那些,因此您不必复制代码,例如
CREATE FUNCTION dbo.add_months_to_datetime
(@dt DATETIME, @interval INT)
RETURNS DATETIME
AS
BEGIN
RETURN DATEADD(MONTH, @interval, @dt);
END
GO
CREATE FUNCTION dbo.add_months_to_date
(@dt DATE, @interval INT)
RETURNS DATE
AS
BEGIN
RETURN dbo.add_months_to_datetime(@dt, @interval);
END
GO
或者,只需始终使用最高精度(第一个功能),并担心在显示数据时它是日期还是日期时间。您可以使用内联转换或适当地将其包装在另一个函数中来执行此操作。
编辑
或者更好的是,只需使用正确的内联日期调用替换对此问题值的所有调用。
dbo.add_months(foo, 1)
变为:
DATEADD(MONTH, 1, foo)
虽然它不像您想要的那样自动,但除了保持输出类型与输入保持相同的要求之外,这还可能会提高某些查询的性能,具体取决于查询中使用这些查询的位置。
答案 1 :(得分:2)
由于SQL Server中标量函数的性能较差,我通常会避免使用或使用Aaron的技术。
但是,如果你必须有这样的语法,你可以使用这样的憎恶:
create function dbo.add_months(@dt sql_variant, @interval int)
returns sql_variant
as
begin
IF SQL_VARIANT_PROPERTY(@dt, 'BaseType') = 'datetime'
return DATEADD(month, @interval, CAST(@dt AS DATETIME))
ELSE IF SQL_VARIANT_PROPERTY(@dt, 'BaseType') = 'date'
return DATEADD(month, @interval, CAST(@dt AS DATE))
RETURN null
end
DECLARE @d DATE = '20120705';
DECLARE @dt DATETIME = '20120705 12:30:30';
SELECT dbo.add_months(@d, 1), dbo.add_months(@dt, 1);
你可以在这个SQLFiddle中看到,现在有问题将数据从sql_variant转移到有用的东西:http://sqlfiddle.com/#!6/f95ba/4