从存储过程调用函数

时间:2017-12-27 09:14:42

标签: sql sql-server sql-server-2008 stored-procedures sql-server-2012

我可以调用未通过存储过程定义的函数吗?

考虑一下我们的存储过程如下:

CREATE PROCEDURE [dbo].[stp__getClients]
AS

BEGIN
    SET NOCOUNT ON;


    Select Id,Name,Status , 
           (CASE WHEN Status = 3 then run_date_calc(FromDate , ToDate) else '' 
            end) as DateRangeDesc
    From ClientsTbl

...
END
GO

我想在Select添加另一个属性:

(CASE WHEN Status = 3 then run_date_calc(FromDate , ToDate) else '' end)

我们想在SP内部创建一个名为run_date_calc的函数 将得到两个日期并返回一个包含其范围描述的字符串 看起来像:

declare @d1 datetime, @d2 datetime, @year int, @month int, @d int
set @d1 = '2009-09-24'
set @d2 = '2012-04-23'

set @year = datediff(year, @d1, @d2) - 1
set @month = datediff(month, dateadd(year, @year, @d1), @d2) 
if dateadd(month, @month, dateadd(year, @year, @d1)) > @d2 set @month = @month - 1

set @d = datediff(day, dateadd(month, @month, dateadd(year, @year, @d1)), @d2)
print cast(@year as nvarchar) + ' year(s) ' + cast(@month as nvarchar) + ' month(s) and ' + cast(@d as nvarchar) + ' day(s)'

是否可以制作一个"内部功能"并在SP内部使用它,而不是在DB中创建它?

由于

3 个答案:

答案 0 :(得分:1)

你不能在SP内“创建”或定义一个函数,没有。您必须在/ a数据库上创建它,然后引用您创建的对象。

如果由于某些奇怪的原因你不希望保留该对象,你可以在TempDB中DROP,使用它,然后/** * Required: set 'ot_theme_mode' filter to true. */ add_filter( 'ot_theme_mode', '__return_true' ); /** * Required: include OptionTree. */ require( trailingslashit( get_template_directory() ) . 'option-tree/ot-loader.php' ); 它(但是这意味着SP不能同时由两个用户运行,因为该对象已经存在)。

只需永久创建它。

答案 1 :(得分:1)

在数据库中创建一个像这样的函数......

CREATE FUNCTION dbo.run_date_calc
(
    @d1 datetime
,   @d2 datetime
)
RETURNS VARCHAR(100)
AS
BEGIN

    Declare @year int, @month int, @d int;

    SET @year = datediff(year, @d1, @d2) - 1
    SET @month = datediff(month, dateadd(year, @year, @d1), @d2) 

    IF dateadd(month, @month, dateadd(year, @year, @d1)) > @d2 set @month = @month - 1

    set @d = datediff(day, dateadd(month, @month, dateadd(year, @year, @d1)), @d2)

    RETURN (  cast(@year  as varchar(10)) + ' year(s) ' 
            + cast(@month as varchar(10)) + ' month(s) and ' 
            + cast(@d     as varchar(10)) + ' day(s)'
            )

END
GO

然后只需从你的proc

调用
CREATE PROCEDURE [dbo].[stp__getClients]
AS

BEGIN
    SET NOCOUNT ON;


    Select Id,Name,Status , 
           (CASE WHEN Status = 3 then dbo.run_date_calc(FromDate , ToDate) else '' 
            end) as DateRangeDesc
    From ClientsTbl

...
END
GO

答案 2 :(得分:1)

正如您所知,您无法在SP内定义功能。 此外,您的功能不正确。 看看我的解决方案:

declare @d1 datetime, @d2 datetime, @year int, @month int, @d int
set @d1 = '2009-09-24'
set @d2 = '2012-04-23'


SET @year = NULLIF(DATEDIFF(year, @d1, @d2), 0)

IF @year IS NOT NULL AND DATEADD(year, @year, @d1) > @d2
    SET @year = NULLIF(@year - 1, 0)

SET @month = NULLIF(DATEDIFF(month, DATEADD(year, ISNULL(@year, 0), @d1), @d2), 0)

IF DATEADD(month, ISNULL(@month, 0), DATEADD(year, ISNULL(@year, 0), @d1)) > @d2 
    set @month = NULLIF(@month - 1, 0)

set @d = DATEDIFF(day, DATEADD(month, ISNULL(@month, 0), DATEADD(year, ISNULL(@year, 0), @d1)), @d2)

SELECT ISNULL(cast(@year as nvarchar) + ' year(s) ', '') + ISNULL(cast(@month as nvarchar) + ' month(s) and ', '') + cast(@d as nvarchar) + ' day(s)'

而不是使用函数你可以使用CASE语句,但在我看来,它看起来很糟糕:

SELECT 
    --Years
    ISNULL(cast(
        CASE WHEN   DATEADD(year, ISNULL(NULLIF(DATEDIFF(year, @d1, @d2), 0), 0), @d1) > @d2 
            THEN NULLIF(DATEDIFF(year, @d1, @d2) - 1, 0)
            ELSE  NULLIF(DATEDIFF(year, @d1, @d2), 0)
            END 
    AS VARCHAR) + ' year(s) ', '')
    --Months
    + ISNULL(cast(

        CASE WHEN DATEADD(month, ISNULL(NULLIF(DATEDIFF(month, DATEADD(year, ISNULL(CASE WHEN   DATEADD(year, ISNULL(NULLIF(DATEDIFF(year, @d1, @d2), 0), 0), @d1) > @d2 
            THEN NULLIF(DATEDIFF(year, @d1, @d2) - 1, 0)
            ELSE  NULLIF(DATEDIFF(year, @d1, @d2), 0)
            END, 0), @d1), @d2), 0), 0), DATEADD(year, ISNULL(CASE WHEN DATEADD(year, ISNULL(NULLIF(DATEDIFF(year, @d1, @d2), 0), 0), @d1) > @d2 
            THEN NULLIF(DATEDIFF(year, @d1, @d2) - 1, 0)
            ELSE  NULLIF(DATEDIFF(year, @d1, @d2), 0)
            END, 0), @d1)) > @d2 
            THEN NULLIF(DATEDIFF(month, DATEADD(year, ISNULL(CASE WHEN  DATEADD(year, ISNULL(NULLIF(DATEDIFF(year, @d1, @d2), 0), 0), @d1) > @d2 
            THEN NULLIF(DATEDIFF(year, @d1, @d2) - 1, 0)
            ELSE  NULLIF(DATEDIFF(year, @d1, @d2), 0)
            END, 0), @d1), @d2) - 1, 0)
            ELSE NULLIF(DATEDIFF(month, DATEADD(year, ISNULL(CASE WHEN  DATEADD(year, ISNULL(NULLIF(DATEDIFF(year, @d1, @d2), 0), 0), @d1) > @d2 
            THEN NULLIF(DATEDIFF(year, @d1, @d2) - 1, 0)
            ELSE  NULLIF(DATEDIFF(year, @d1, @d2), 0)
            END, 0), @d1), @d2), 0)
            END
        AS VARCHAR) + ' month(s) ', '')
    --Days 
     + cast(DATEDIFF(day, DATEADD(month, ISNULL(CASE WHEN DATEADD(month, ISNULL(NULLIF(DATEDIFF(month, DATEADD(year, ISNULL(CASE WHEN   DATEADD(year, ISNULL(NULLIF(DATEDIFF(year, @d1, @d2), 0), 0), @d1) > @d2 
            THEN NULLIF(DATEDIFF(year, @d1, @d2) - 1, 0)
            ELSE  NULLIF(DATEDIFF(year, @d1, @d2), 0)
            END, 0), @d1), @d2), 0), 0), DATEADD(year, ISNULL(CASE WHEN DATEADD(year, ISNULL(NULLIF(DATEDIFF(year, @d1, @d2), 0), 0), @d1) > @d2 
            THEN NULLIF(DATEDIFF(year, @d1, @d2) - 1, 0)
            ELSE  NULLIF(DATEDIFF(year, @d1, @d2), 0)
            END, 0), @d1)) > @d2 
            THEN NULLIF(DATEDIFF(month, DATEADD(year, ISNULL(CASE WHEN  DATEADD(year, ISNULL(NULLIF(DATEDIFF(year, @d1, @d2), 0), 0), @d1) > @d2 
            THEN NULLIF(DATEDIFF(year, @d1, @d2) - 1, 0)
            ELSE  NULLIF(DATEDIFF(year, @d1, @d2), 0)
            END, 0), @d1), @d2) - 1, 0)
            ELSE NULLIF(DATEDIFF(month, DATEADD(year, ISNULL(CASE WHEN  DATEADD(year, ISNULL(NULLIF(DATEDIFF(year, @d1, @d2), 0), 0), @d1) > @d2 
            THEN NULLIF(DATEDIFF(year, @d1, @d2) - 1, 0)
            ELSE  NULLIF(DATEDIFF(year, @d1, @d2), 0)
            END, 0), @d1), @d2), 0)
            END, 0), DATEADD(year, ISNULL(CASE WHEN DATEADD(year, ISNULL(NULLIF(DATEDIFF(year, @d1, @d2), 0), 0), @d1) > @d2 
            THEN NULLIF(DATEDIFF(year, @d1, @d2) - 1, 0)
            ELSE  NULLIF(DATEDIFF(year, @d1, @d2), 0)
            END , 0), @d1)), @d2) as nvarchar) + ' day(s)'