TSQL标量函数

时间:2016-06-21 15:55:33

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

我创建了一个小函数,它接受一些日期参数并根据我定义的逻辑输出项目状态。

我试图找出一旦设置状态后我怎么能“突破”该功能。在我下面的逻辑中,它似乎始终检查dueDate并设置其状态,然后通过以下检查覆盖它。

ALTER FUNCTION [dbo].[Fetch_TaskStatus]
(
    -- Add the parameters for the function here
    @startDate DATE = NULL,
    @dueDate DATE = NULL,
    @completionDate DATE = NULL
)
RETURNS varchar(100)
AS
BEGIN
    -- Declare the return variable here
    DECLARE @status varchar(100);

    -- Declare our current date
    DECLARE @now DATE = GETUTCDATE();

    -- Logic
    -- If our start date and completion date are missing..
    IF(@startDate IS NULL AND @completionDate IS NULL)
        BEGIN

            -- If our due date is past the current date, its past due
            IF(@dueDate < @now)
            BEGIN
                SET @status = 'Past Due';
            END

            -- We have a start date but the task has not been started.
            SET @status = 'Inactive';

        END

        -- If we have a start date and no completion date
    IF(@startDate IS NOT NULL AND @completionDate IS NULL)
        BEGIN

            -- Are we past due?
            IF(@dueDate < @now)
                BEGIN
                    SET @status = 'Past Due'
                END

            -- We are not past due, must be in progress
            SET @status = 'In Progress'

        END

    -- If we have a start date and a completion date
    IF(@startDate IS NOT NULL AND @completionDate IS NOT NULL)

        BEGIN
            -- We have started and completed our task
            SET @status = 'Complete'
        END

    -- Return the result of the function
    RETURN @status

END

一旦设置了状态,我需要打破这个功能,以便状态不会被其后面的逻辑再次覆盖。

有没有更好的方法来解决这个问题?

3 个答案:

答案 0 :(得分:2)

重写如下:

ALTER FUNCTION [dbo].[Fetch_TaskStatus]
(
-- Add the parameters for the function here
@startDate DATE = NULL,
@dueDate DATE = NULL,
@completionDate DATE = NULL
)
RETURNS varchar(100)
AS
BEGIN
-- Declare the return variable here
DECLARE @status varchar(100);

-- Declare our current date
DECLARE @now DATE = GETUTCDATE();

-- Logic
-- If our start date and completion date are missing..
IF(@startDate IS NULL AND @completionDate IS NULL)
    BEGIN

        -- If our due date is past the current date, its past due
        IF(@dueDate < @now)
        BEGIN
            RETURN  'Past Due';

        END

        -- We have a start date but the task has not been started.
            RETURN  'Inactive';

    END

    -- If we have a start date and no completion date
IF(@startDate IS NOT NULL AND @completionDate IS NULL)
    BEGIN

        -- Are we past due?
        IF(@dueDate < @now)
            BEGIN
            RETURN  'Past Due'

            END

        -- We are not past due, must be in progress
            RETURN  'In Progress'

    END

-- If we have a start date and a completion date
IF(@startDate IS NOT NULL AND @completionDate IS NOT NULL)

    BEGIN
        -- We have started and completed our task
            RETURN  'Complete'
    END

-- Return the result of the function
RETURN 'Unknown';

END

您还可以使用IF-ELSE块。我也使用IF-ELSE重写它,只是检查你的逻辑是否得到保证:

    CREATE FUNCTION [dbo].[Fetch_TaskStatus]
    (
      -- Add the parameters for the function here
      @startDate DATE = NULL ,
      @dueDate DATE = NULL ,
      @completionDate DATE = NULL
    )
 RETURNS VARCHAR(100)
AS
    BEGIN

-- Declare our current date
        DECLARE @now DATE = GETUTCDATE();

-- Logic
-- If our start date and completion date are missing..
        IF ( @startDate IS NULL
             AND @completionDate IS NULL
           )
            BEGIN
         -- If our due date is past the current date, its past due
                IF ( @dueDate < @now )
                    RETURN  'Past Due';
                ELSE
                        -- We have a start date but the task has not been started.
                    RETURN  'Inactive';
            END;

    -- If we have a start date and no completion date
        IF ( @startDate IS NOT NULL
             AND @completionDate IS NULL
           )
            BEGIN
            -- Are we past due?
                IF ( @dueDate < @now )
                    RETURN  'Past Due';
                ELSE
                        -- We are not past due, must be in progress
                    RETURN  'In Progress';
            END;

-- If we have a start date and a completion date
        IF ( @startDate IS NOT NULL
             AND @completionDate IS NOT NULL
           )
            -- We have started and completed our task
            RETURN  'Complete';

      -- Return the result of the function
        RETURN 'Unknown';
    END;

答案 1 :(得分:0)

这里采用完全不同的方法怎么样?标量函数非常低效且不灵活。通常更好的方法是使用内联表值函数。这意味着您必须使用单个select语句。当然,您的整个嵌套IF语句系列可以压缩为几个case表达式。这样维护起来更简单,更灵活,性能更好。

ALTER FUNCTION [dbo].[Fetch_TaskStatus]
(
    @startDate DATE = NULL,
    @dueDate DATE = NULL,
    @completionDate DATE = NULL
)
RETURNS table as return
    select TaskStatus = 
        Case
            WHEN @startDate IS NULL AND @completionDate IS NULL then
                Case when @dueDate < GETUTCDATE() then 'Past Due' else 'Inactive' end

            WHEN @startDate IS NOT NULL AND @completionDate IS NULL then
                Case when @dueDate < GETUTCDATE() then 'Past Due' else 'In Progress' end
            WHEN @startDate IS NOT NULL AND @completionDate IS NOT NULL then 'Complete'
        END

答案 2 :(得分:0)

CREATE FUNCTION [dbo].[Fetch_TaskStatus] (
     -- Add the parameters for the function here
     @startDate DATE = NULL,
     @dueDate DATE = NULL,
     @completionDate DATE = NULL
    )
RETURNS VARCHAR(100)
AS 
    BEGIN
    -- Declare our current date
        DECLARE @now DATE = GETUTCDATE();

        RETURN CASE WHEN @startDate IS NOT NULL AND @completionDate IS NOT NULL THEN 'Complete'
                    WHEN @dueDate < @now THEN 'Past Due'
                    WHEN @startDate IS NOT NULL AND @completionDate IS NULL THEN 'In Progress'
                    WHEN @startDate IS NULL AND @completionDate IS NULL THEN 'Inactive'
                    END
    END

这应该涵盖你的逻辑