Problem with Table-Valued Functions

Villa 231 Reputation points
2021-01-07T20:27:35.123+00:00

I created a function to return a value.
When I called the function, for unknown reason (to me, it is unknown), I did not get the result.

Here is how I called the function:

SELECT * FROM cu.fnBIDouangTest('12/28/2020',2);

Here is my function:

ALTER FUNCTION cu.fnBIDouangTest(@SettlementDate DATE,@count int)

RETURNS @FinalFundingDate TABLE (FundingDate DATE)

AS

BEGIN


--Create Holidays temp table    
DECLARE @TblHoliday AS TABLE (Holiday_Date DATE)  
INSERT INTO @TblHoliday --(populating holidays from DimDate table)
    SELECT 
        FullDate Holiday_Date 
    FROM DBO.dimDate d

    WHERE d.IsUSCivilHoliday = 'Y'
        AND YearNum >= 2019


--Running through the loop twice
  DECLARE @FundingDate DATE
  DECLARE @i int = 1; -- my "iterator"
  WHILE @i <= @count
  BEGIN
    SET @FundingDate = dateadd(day,  -1, @Settlementdate)

    WHILE ((SELECT TOP 1 1
                FROM @TblHoliday
                WHERE Holiday_Date = @FundingDate) = 1 OR datename(dw, @FundingDate) IN ('Saturday', 'Sunday'))
        BEGIN
            SET @FundingDate = dateadd(day, - 1, @FundingDate)
        END

        SET @i = @i+1
        SET @Settlementdate = @FundingDate
    END

RETURN;

END

When I run the function as a static query,
example here:

DECLARE @SettlementDate DATE = '12/28/2020'
DECLARE @count INT = 2

BEGIN

--Create Holidays temp table    
DECLARE @TblHoliday AS TABLE (Holiday_Date DATE)  
INSERT INTO @TblHoliday --(populating holidays from DimDate table)
    SELECT 
        FullDate Holiday_Date 
    FROM DBO.dimDate d

    WHERE d.IsUSCivilHoliday = 'Y'
        AND YearNum >= 2019

--Beginning of the loop
  DECLARE @FundingDate DATE
  DECLARE @i int = 1; -- my "iterator"
  WHILE @i <= @count
  BEGIN
    SET @FundingDate = dateadd(day,  -1, @Settlementdate)

    WHILE ((SELECT TOP 1 1
                FROM @TblHoliday
                WHERE Holiday_Date = @FundingDate) = 1 OR datename(dw, @FundingDate) IN ('Saturday', 'Sunday'))
        BEGIN
            SET @FundingDate = dateadd(day, - 1, @FundingDate)
        END

        SET @i = @i+1
        SET @Settlementdate = @FundingDate
    END

END

SELECT @Settlementdate

I get the result as 2020-12-23 which is correct.

But, I just don't see why I don't get the result when I turned the above code into a function.

Thank you in advance for your help.

Transact-SQL
Transact-SQL
A Microsoft extension to the ANSI SQL language that includes procedural programming, local variables, and various support functions.
4,640 questions
0 comments No comments
{count} votes

Accepted answer
  1. Tom Phillips 17,731 Reputation points
    2021-01-07T21:38:13.76+00:00

    I assume you are questioning why you get no result at all from your function. That is because you created a function which returns a table, but you didn't populate the table.

    You are only returning a single value, you should just use a scalar function.
    CREATE OR ALTER FUNCTION dbo.fnBIDouangTest(@SettlementDate DATE,@count int)

     RETURNS DATE
    
     AS
    
     BEGIN
    
    
     --Create Holidays temp table    
     DECLARE @TblHoliday AS TABLE (Holiday_Date DATE)  
     INSERT INTO @TblHoliday --(populating holidays from DimDate table)
         SELECT 
             FullDate Holiday_Date 
         FROM DBO.dimDate d
    
         WHERE d.IsUSCivilHoliday = 'Y'
             AND YearNum >= 2019
    
     --Running through the loop twice
       DECLARE @FundingDate DATE
       DECLARE @i int = 1; -- my "iterator"
       WHILE @i <= @count
       BEGIN
         SET @FundingDate = dateadd(day,  -1, @Settlementdate)
    
         WHILE ((SELECT TOP 1 1
                     FROM @TblHoliday
                     WHERE Holiday_Date = @FundingDate) = 1 OR datename(dw, @FundingDate) IN ('Saturday', 'Sunday'))
             BEGIN
                 SET @FundingDate = dateadd(day, - 1, @FundingDate)
             END
    
             SET @i = @i+1
             SET @Settlementdate = @FundingDate
         END
    
     RETURN @FundingDate;
    
     END
    

1 additional answer

Sort by: Most helpful
  1. Tom Phillips 17,731 Reputation points
    2021-01-07T21:56:40.923+00:00

    PS. You don't need to loop to get the value you are looking for:

    CREATE OR ALTER FUNCTION dbo.udf_SubBusinessDays
        (@Date date, @BusinessDays int)
    RETURNS date
    AS
    BEGIN
          RETURN (
                SELECT TOP (1) FullDate AS BusinessDate
                FROM (SELECT TOP (@BusinessDays) FullDate
                      FROM dbo.dimDate
                      WHERE
                            FullDate < @Date
                            AND IsUSCivilHoliday <> 'Y'
                                AND datename(dw, FullDate) NOT IN ('Saturday', 'Sunday')
                      ORDER BY FullDate DESC) AS BusinessDays
                ORDER BY FullDate ASC
          )
    END
    
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.