简体   繁体   中英

Call a function from Stored Procedure

Can I call a function that is not defined from a Stored Procedure ?

Consider we have a Stored Procedure that looks like that :

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

I want to add another property to the Select like that :

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

We want to create a function inside the SP called run_date_calc that will get two dates and return a string with its range description looks like :

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)'

Is it possible to make an "inside function" and use it inside the SP , without creating it in the DB ?

Thanks

You can't "create" or define a function inside an SP, no. You'll have to create it on the/a database and then reference the object you created.

If, for some odd reason you don't want the object to remain, you could CREATE it in TempDB, use it, and then DROP it (but this would mean the SP cannot be run by two users simultaneously, as the object would already exist).

Just create it permanently.

Create a function in the database like this...

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

And then simply call if from your 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

As you were informed, you can't define a function inside an SP. Besides, your function is incorrect. Look at my solution:

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)'

Instead of using a function you could use CASE statement, but in my opinion, it looks terrible:

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)'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM