创建函数错误sql server 2008

时间:2014-05-19 11:11:57

标签: sql-server-2008

我想创建一个函数,但是会出错。 以下是查询:

CREATE FUNCTION WFSlaTimer
(
 @OBJECT_PK_ID  INT = 110
)
RETURNS TABLE
AS BEGIN
        DECLARE
        @TIMER_START_ACTIVITY_ID            INT,
        @TIMER_START_ACTIVITY_COMPLETED_ON  DATETIME,

        @TIMER_END_ACTIVITY_ID              INT,
        @TIMER_END_ACTIVITY_COMPLETED_ON    DATETIME,

        @SLA_TIME_SCHEDULE_IN_DAYS          INT,
        @SLA_DISPLAY                        VARCHAR(20),
        @START_DATE                         DATETIME,
        @END_DATE                           DATETIME,
        @BUSINESS_START_TIME                VARCHAR(10),
        @BUSINESS_END_TIME                  VARCHAR(10),
        @BUSINESS_HOURS                     INT,
        @SLA_CUT_OFF_TIME                   VARCHAR(10),
        @IS_OBJECT_STATUS_IS_TERMINAL       INT,
        @COMPLETED_ACTION_ID                INT,
        @UNCHECKED_ACTION_ID                INT,
        @DAY_ADDED                          INT

        SELECT @IS_OBJECT_STATUS_IS_TERMINAL = CASE when wos.FLG_STATUS_TYPE = 'W' THEN 0 ELSE 1 END  
        FROM WF.WF_OBJECT_INSTANCE woi
        INNER JOIN WF.WF_OBJECT_STATUS wos ON wos.OBJECT_STATUS_ID = woi.OBJECT_STATUS_ID
        WHERE woi.LINK_PK_ID = @OBJECT_PK_ID



    SET @SLA_TIME_SCHEDULE_IN_DAYS = (SELECT CASE WHEN s.SLA_SCHEDULE_ID = 1 THEN lr.RUSH_NO_OF_DAYS ELSE s.NUM_OF_DAYS END --1= [RUSH]
                                            FROM loan.LOAN_REQUEST lr 
                                             INNER JOIN WF.WF_SLA_SCHEDULE s 
                                             ON s.SLA_SCHEDULE_ID = ISNULL(lr.SLA_SCHEDULE_ID, 2) --{2= SLA-Schedule 5 Days} 
                                             WHERE lr.LOAN_REQUEST_ID = @OBJECT_PK_ID)

     SET @SLA_DISPLAY = (SELECT
     CASE WHEN s.SLA_SCHEDULE_ID = 1 THEN s.DISPLAY_NAME + ' (' + CAST(lr.RUSH_NO_OF_DAYS AS VARCHAR) + ')' ELSE s.DISPLAY_NAME END --1= [RUSH] 
                                FROM loan.LOAN_REQUEST lr 
                                 INNER JOIN WF.WF_SLA_SCHEDULE s 
                                 ON s.SLA_SCHEDULE_ID = ISNULL(lr.SLA_SCHEDULE_ID, 2) --{2= SLA-Schedule 5 Days}
                                 WHERE lr.LOAN_REQUEST_ID = @OBJECT_PK_ID)                                        

    SET @BUSINESS_START_TIME =  (SELECT s.CONFIG_VALUE FROM SYS_CONFIG_ENTRY s WHERE s.NAME = 'BUSINESS_START_TIME')
    SET @BUSINESS_END_TIME   =  (SELECT s.CONFIG_VALUE FROM SYS_CONFIG_ENTRY s WHERE s.NAME = 'BUSINESS_END_TIME')
    SET @BUSINESS_HOURS  = (SELECT CAST(DATEDIFF(hour, CAST(@BUSINESS_START_TIME AS DATETIME), CAST(@BUSINESS_END_TIME AS DATETIME)) AS INT))

    SET @SLA_CUT_OFF_TIME    =  (SELECT DATEPART(hour, CAST(s.CONFIG_VALUE AS TIME)) FROM SYS_CONFIG_ENTRY s WHERE s.NAME = 'SLA_CUT_OFF_TIME')
    SET @COMPLETED_ACTION_ID =  (SELECT ACTION_TYPE_ID FROM WF.WF_ACTION_TYPE WHERE NAME = 'ACTIVITY_COMPLETED')
    SET @UNCHECKED_ACTION_ID =  (SELECT ACTION_TYPE_ID FROM WF.WF_ACTION_TYPE WHERE NAME = 'ACTIVITY_UNCHECKED')

    --GET SLA TIMER ACTIVITY IDs
    SELECT  @TIMER_START_ACTIVITY_ID = t.START_ACTIVITY_ID, 
            @TIMER_END_ACTIVITY_ID   = t.END_ACTIVITY_ID 
    FROM    [WF].WF_TIMER t 
    WHERE   t.NAME = 'SLA_TIMER'

    --Get START ACTIVITY ON
    SELECT  @TIMER_START_ACTIVITY_COMPLETED_ON = ACTION_ON 
    FROM    [WF].WF_OBJECT_ACTIVITY_HISTORY woah
    WHERE   LINK_PK_ID = @OBJECT_PK_ID
            AND woah.ACTIVITY_ID = @TIMER_START_ACTIVITY_ID
            AND ACTION_ID = @COMPLETED_ACTION_ID
            AND
            --{  
            woah.APPLICATION_HISTORY_ID > ISNULL((SELECT TOP 1 ISNULL(APPLICATION_HISTORY_ID, 0) 
                             FROM   WF.WF_OBJECT_ACTIVITY_HISTORY 
                             WHERE  LINK_PK_ID = @OBJECT_PK_ID
                                    AND  ACTIVITY_ID = @TIMER_START_ACTIVITY_ID
                                    AND  ACTION_ID = @UNCHECKED_ACTION_ID
                             ORDER BY ACTION_ON DESC 
            ), 0)
            --}
            --AND
            ----{
            --0 = ISNULL((SELECT TOP 1 ISNULL(APPLICATION_HISTORY_ID, 0) 
            --                 FROM WF.WF_OBJECT_ACTIVITY_HISTORY 
            --                 WHERE    LINK_PK_ID = @OBJECT_PK_ID
            --               AND    ACTIVITY_ID = @TIMER_END_ACTIVITY_ID
            --               AND    ACTION_ID = @COMPLETED_ACTION_ID
            --                 ORDER BY ACTION_ON DESC), 0)
            ----}
    ORDER BY ACTION_ON DESC

    --Get END ACTIVITY ON       
    SELECT  @TIMER_END_ACTIVITY_COMPLETED_ON = ACTION_ON 
    FROM    [WF].WF_OBJECT_ACTIVITY_HISTORY woah
    WHERE   LINK_PK_ID = @OBJECT_PK_ID
            AND woah.ACTIVITY_ID = @TIMER_END_ACTIVITY_ID
            AND ACTION_ID = @COMPLETED_ACTION_ID
            AND
            --{  
            woah.APPLICATION_HISTORY_ID > ISNULL((SELECT TOP 1 ISNULL(APPLICATION_HISTORY_ID, 0) 
                             FROM   WF.WF_OBJECT_ACTIVITY_HISTORY 
                             WHERE  LINK_PK_ID = @OBJECT_PK_ID
                                    AND  ACTIVITY_ID = @TIMER_END_ACTIVITY_ID
                                    AND  ACTION_ID = @UNCHECKED_ACTION_ID
                             ORDER BY ACTION_ON DESC 
            ), 0)
            --}
    ORDER BY ACTION_ON DESC

    --TO DO
    --SET @TIMER_START_ACTIVITY_COMPLETED_ON = '2014-05-15 02:40:21.100'
    --SET @TIMER_END_ACTIVITY_COMPLETED_ON = '2014-05-14 12:40:21.100'

    SET @START_DATE =  @TIMER_START_ACTIVITY_COMPLETED_ON

    SET @DAY_ADDED = @SLA_TIME_SCHEDULE_IN_DAYS -- SLA Schedule Days
                     + CASE WHEN DATEPART(hour, @TIMER_START_ACTIVITY_COMPLETED_ON) >= @SLA_CUT_OFF_TIME THEN 0 ELSE -1 END -- SLA Cut Off Time

    SET @END_DATE = @START_DATE + @DAY_ADDED

    --Exclud Holidays
    --{
    DECLARE @START_ON_DATE  DATETIME = CAST(@START_DATE AS DATE)
    WHILE  @DAY_ADDED > 0 
        BEGIN
            SELECT @END_DATE =  @START_ON_DATE + @DAY_ADDED 
            --COUNT NO OF HOLIDAYS IF FALLING WITHIN START-DATE AND END-DATE
            SELECT @DAY_ADDED = COUNT(*)  FROM [WF].WF_CALENDAR WC --HOLIDAY LIST
            WHERE WC.DATE BETWEEN @START_ON_DATE+1 AND @END_DATE AND (WC.IS_WEEKEND = 1 OR WC.IS_HOLIDAY = 1)
            SET @START_ON_DATE = @END_DATE
        END
    --}
    SET @END_DATE = (CAST(CAST(CAST(@END_DATE AS DATE) AS DATETIME) + CAST(@BUSINESS_END_TIME AS TIME) AS DATETIME))

    ;WITH TIMER_CTE AS (
                        SELECT  @START_DATE AS OBJECT_CREATED_ON, 
                                @END_DATE AS OBJECT_END_ON,
                                DIFFERENCE_IN_DAYS = DATEDIFF(dd, GETDATE(), @END_DATE),
                                TODAY_REMAINING_MINUTES =
                                CASE WHEN  CONVERT(VARCHAR(10), @END_DATE, 112) >= CONVERT(VARCHAR(10), GETDATE(), 112)
                                    THEN DATEDIFF(minute, GETDATE(), (CAST(CAST(CAST(GETDATE() AS DATE) AS DATETIME) + CAST(@BUSINESS_END_TIME AS TIME) AS DATETIME))) 
                                ELSE 0 END,
                                TODAY_REMAINING_HOURS =  
                                CASE WHEN CONVERT(VARCHAR(10), @END_DATE, 112) >= CONVERT(VARCHAR(10), GETDATE(), 112) 
                                    THEN (DATEDIFF(minute, GETDATE(), (CAST(CAST(CAST(GETDATE() AS DATE) AS DATETIME) + CAST(@BUSINESS_END_TIME AS TIME) AS DATETIME)))/60) 
                                ELSE 0 END
    )
RETURN ( 
    SELECT

    IS_SHOW_SLA = CASE WHEN @TIMER_START_ACTIVITY_COMPLETED_ON IS NULL 
                    --OR  @IS_OBJECT_STATUS_IS_TERMINAL = 1 

                    --OR @TIMER_START_ACTIVITY_COMPLETED_ON IS NULL 
                    THEN 0 
                    ELSE 1 END,
    @START_DATE AS [START_DATE], @END_DATE AS [END_DATE],
    SLA_TYPE = @SLA_DISPLAY,
    SLA_DUE = CONVERT(VARCHAR(10), CONVERT(DATETIME, tc.OBJECT_END_ON, 1), 101),
    @BUSINESS_END_TIME AS BUSINESS_END_TIME,
    SLA_START_ACTIVITY_CHECKED_ON = tc.OBJECT_CREATED_ON,
    SLA_END_ACTIVITY_CHECKED_ON = @TIMER_END_ACTIVITY_COMPLETED_ON,
    SLA_MISSED = CASE WHEN 
                        --TODAY_REMAINING_MINUTES <= 0 
                        --AND CONVERT(VARCHAR(10), @END_DATE, 112) = CONVERT(VARCHAR(10), GETDATE(), 112)
                        --OR 
                        ( GETDATE()> @END_DATE) 
                        OR @TIMER_START_ACTIVITY_COMPLETED_ON IS NULL 
                        THEN 'Missed' ELSE NULL END,
    tc.TODAY_REMAINING_HOURS,
    tc.TODAY_REMAINING_MINUTES,
    LAST_DAY_TIME_REMAINING =
    CASE 
    WHEN @TIMER_END_ACTIVITY_COMPLETED_ON <= @END_DATE THEN 'Successful Completed'
    WHEN CONVERT(VARCHAR(10), @END_DATE, 112) = CONVERT(VARCHAR(10), GETDATE(), 112)
    THEN  
        CASE WHEN 
        tc.TODAY_REMAINING_HOURS <=0 AND tc.TODAY_REMAINING_MINUTES > 0 THEN 
            CASE WHEN tc.TODAY_REMAINING_MINUTES = 1 THEN CAST(tc.TODAY_REMAINING_MINUTES AS VARCHAR) + ' min remaining'
            ELSE CAST(tc.TODAY_REMAINING_MINUTES AS VARCHAR) + ' mins remaining' END
                                   WHEN tc.TODAY_REMAINING_HOURS =1 THEN CAST(tc.TODAY_REMAINING_HOURS AS VARCHAR) + ' hour remaining' 
                                   WHEN tc.TODAY_REMAINING_HOURS >1 THEN CAST(tc.TODAY_REMAINING_HOURS AS VARCHAR) + ' hours remaining'
                                   ELSE NULL 
        END
        ELSE NULL
    END,

    REMAINING_DAYS = CASE WHEN tc.DIFFERENCE_IN_DAYS <=0 THEN '0 day'
                        WHEN tc.DIFFERENCE_IN_DAYS > 1 THEN CAST(tc.DIFFERENCE_IN_DAYS AS VARCHAR) + ' days ' 
                        ELSE CAST(tc.DIFFERENCE_IN_DAYS AS VARCHAR) + ' day ' END 
    FROM TIMER_CTE tc
)
END;
GO

我收到此错误:

Msg 156, Level 15, State 1, Procedure WFSlaTimer, Line 144
Incorrect syntax near the keyword 'RETURN'.
Msg 178, Level 15, State 1, Procedure WFSlaTimer, Line 144
A RETURN statement with a return value cannot be used in this context.
Msg 102, Level 15, State 31, Procedure WFSlaTimer, Line 189
Incorrect syntax near 'BEGIN'.

请帮助

2 个答案:

答案 0 :(得分:1)

返回表有两种功能。内联函数和多语句函数。你的是多语句。以下是此语法:

--Transact-SQL Multistatement Table-valued Function Syntax
CREATE FUNCTION [ schema_name. ] function_name 
( [ { @parameter_name [ AS ] [ type_schema_name. ] parameter_data_type 
    [ = default ] [READONLY] } 
    [ ,...n ]
  ]
)
RETURNS @return_variable TABLE <table_type_definition>
    [ WITH <function_option> [ ,...n ] ]
    [ AS ]
    BEGIN 
        function_body 
        RETURN
    END
[ ; ]

有关更多信息,请参阅CREATE FUNCTION (Transact-SQL) BOL文档。

答案 1 :(得分:0)

您必须定义返回表格的结构(字段和数据类型)

1)在函数定义中添加变量名称(上例中为@tableVariable)。 2)填写表定义(列和数据类型) 3)修改函数以将结果插入到已定义的表变量中,然后在函数返回时使用空RETURN语句。

第一步

CREATE FUNCTION WFSlaTimer
(
 @OBJECT_PK_ID  INT = 110
)
RETURNS @tableVariable TABLE ( 
    IS_SHOW_SLA INT,
    StartDate DATETIME2,
    EndDate DATETIME2
    /** List all of your returned columns like when you creating a table **/
)
AS
BEGIN
    /** Do your stuff **/
    INSERT INTO @tableVariable ( /* field list */) VALUES (/* value list */)
    -- OR --
    INSERT INTO @tableVariable ( /* field list */)
    SELECT /* FieldList */ FROM myCTE


    RETURN
END

第二步

修改你的RETURN()语句,如下所示:

INSERT INTO @tableVanriable (IS_SHOW_SLA , StartDate , EndDate)
SELECT
    IS_SHOW_SLA = CASE WHEN @TIMER_START_ACTIVITY_COMPLETED_ON IS NULL 
                --OR  @IS_OBJECT_STATUS_IS_TERMINAL = 1 

                --OR @TIMER_START_ACTIVITY_COMPLETED_ON IS NULL 
                THEN 0 
                ELSE 1 END,
    @START_DATE AS [START_DATE], @END_DATE AS [END_DATE],
    SLA_TYPE = @SLA_DISPLAY

    /** .... **/

FROM TIMER_CTE tc

/** 3rd step **/
RETURN