【问题标题】:TSQL Scalar FunctionTSQL 标量函数
【发布时间】:2016-06-21 15:55:32
【问题描述】:

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

我试图弄清楚一旦设置了状态,我如何“打破”该功能。在我下面的逻辑中,它似乎总是会检查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

一旦设置了状态,我需要退出这个函数,这样状态就不会被后面的逻辑再次覆盖。

有没有更好的方法来处理这个问题?

【问题讨论】:

  • 为什么不在IF 语句中只使用RETURN 而不是设置变量?
  • 为什么不早点RETURN?或使用嵌套的IF 块,如果您想坚持“只有 1 个返回语句”

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


【解决方案1】:

改写如下:

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;

【讨论】:

    【解决方案2】:

    这里采用完全不同的方法怎么样?标量函数效率极低,而且不是很灵活。通常更好的方法是使用内联表值函数。这意味着您必须使用单个 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
    

    【讨论】:

      【解决方案3】:
      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
      

      这应该涵盖你的逻辑

      【讨论】:

        猜你喜欢
        • 2012-02-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-23
        • 1970-01-01
        • 2013-07-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多