【问题标题】:How do you minimize the nesting level within a function?如何最小化函数中的嵌套级别?
【发布时间】:2017-03-18 16:21:12
【问题描述】:

我目前收到此错误:

消息 217,第 16 层,状态 1,第 127 行
超出最大存储过程、函数、触发器或视图嵌套级别(限制 32)

如何最小化嵌套级别?我做了一些研究,发现有人使用过 go each end,但这对我不起作用。

--Function: StateFilingStatus
create function dbo.GetStateFilingStatus(@EmpFederalFilingStatus char(1), @EmpTransferState char(2))
returns char(1)
as
begin
    declare @StateFilingStatus char;

    if (@EmpTransferState = 'MS') 
    begin
        if (@EmpFederalFilingStatus = 'S')
            set @StateFilingStatus = 'A';
        else
            set @StateFilingStatus = 'M';
    end
    else if (@EmpTransferState = 'NJ') 
    begin
         if (@EmpFederalFilingStatus = 'S')
             set @StateFilingStatus = 'B';
         else
             set @StateFilingStatus = 'A';
    end
    else if (@EmpTransferState = 'AZ') 
    begin
        if (@EmpFederalFilingStatus = 'S')
            set @StateFilingStatus = 'A';
        else
            set @StateFilingStatus = 'B';
    end
    else if (@EmpTransferState = 'CT') 
    begin
         if (@EmpFederalFilingStatus = 'S')
            set @StateFilingStatus = 'F';
         else
            set @StateFilingStatus = 'M';
    end
    else if (@EmpTransferState = 'DC') 
    begin
        if (@EmpFederalFilingStatus = 'S')
            set @StateFilingStatus = 'S';
        else
            set @StateFilingStatus = 'Y';
    end
    else
    begin   
        if (@EmpFederalFilingStatus = 'S')
            set @StateFilingStatus = 'S';
        else
            set @StateFilingStatus = 'M';
    end

    return (select dbo.GetStateFilingStatus(EmpFederalFilingStatus, EmpTransferState) as StateFilingStatus
            from EmployeeTransfers)
end
go

select dbo.GetStateFilingStatus('M','NJ')  as StateFilingStatus

【问题讨论】:

    标签: sql-server-2008 user-defined-functions


    【解决方案1】:

    目前,您的嵌套问题是由于return 格式不正确造成的。

    代替:

    return(
        select dbo.GetStateFilingStatus(EmpFederalFilingStatus, EmpTransferState) as StateFilingStatus
        from EmployeeTransfers
    )
    

    你会使用:

      return @StateFilingStatus;
    

    rextester 演示:http://rextester.com/DJM36125

    --Function: StateFilingStatus
    create function dbo.GetStateFilingStatus(
        @EmpFederalFilingStatus char(1)
      , @EmpTransferState char(2)
      )
    returns char(1) as
    begin;
      declare @StateFilingStatus char(1);
      if (@EmpTransferState = 'MS') 
      begin;
        if (@EmpFederalFilingStatus = 'S')
          set @StateFilingStatus = 'A';
        else
          set @StateFilingStatus = 'M';
      end;
      else
      if (@EmpTransferState = 'NJ') 
      begin;
        if (@EmpFederalFilingStatus = 'S')
          set @StateFilingStatus = 'B';
        else
          set @StateFilingStatus = 'A';
      end;
      else
      if (@EmpTransferState = 'AZ') 
      begin;
        if (@EmpFederalFilingStatus = 'S')
          set @StateFilingStatus = 'A';
        else
          set @StateFilingStatus = 'B';
      end;
      else
      if (@EmpTransferState = 'CT') 
      begin;
        if (@EmpFederalFilingStatus = 'S')
          set @StateFilingStatus = 'F';
        else
          set @StateFilingStatus = 'M';
      end;
      else
      if (@EmpTransferState = 'DC') 
      begin;
        if (@EmpFederalFilingStatus = 'S')
          set @StateFilingStatus = 'S';
        else
          set @StateFilingStatus = 'Y';
      end;
      else
      begin   
        if (@EmpFederalFilingStatus = 'S')
          set @StateFilingStatus = 'S';
        else
          set @StateFilingStatus = 'M';
      end;
      return @StateFilingStatus;
    end;
    go
    select StateFilingStatus = dbo.GetStateFilingStatus('','NJ');
    

    返回A

    由于这是一个标量函数,您可以使用以下方式查询它:

    select 
        et.EmpFederalFilingStatus
      , StateFilingStatus = dbo.GetStateFilingStatus(et.EmpFederalFilingStatus,et.EmpTransferState)
    from EmployeeTransfers et
    

    像这样的标量函数会导致可怕的性能问题。只要有可能,函数就应该写成内联表值函数。

    如果这不是学习练习,我建议使用人行横道表(正如我的其他答案所解释的那样)。

    参考:

    【讨论】:

    • 如您所说,这纯粹是为了学习练习。接下来我将使用另一个数据库尝试人行横道表。我确实对“等”有疑问。你用过,是什么意思?
    • @Danny 这是表名EmployeeTransfers 的别名,因此我们不必到处输入EmployeeTransfers 来指定列的表。 from EmployeeTransfers etfrom EmployeeTransfers as et 相同。这是一个例子:rextester.com/SLLD96236
    【解决方案2】:

    与其根据具体情况处理所有这些问题,不如创建一个人行横道表?

    create table Filing_State_xwalk (
        TransferState char(2) not null
      , FederalStatus char(1) not null
      , StateStatus   char(1) not null
      , constraint pk_Filing_State_xwalk 
          primary key (TransferState, FederalStatus)
    );
    insert into Filing_State_xwalk values
     ('MS','S','A')
    ,('MS',' ','M')
    ,('NJ','S','B')
    ,('NJ',' ','A')
    ,('AZ','S','A')
    ,('AZ',' ','M')
    ,('CT','S','F')
    ,('CT',' ','M')
    ,('DC','S','S')
    ,('DC',' ','Y');
    

    并在这样的过程中使用它:

    set @StateFilingStatus = (
      select StateStatus
      from Filing_State_xwalk
      where TransferState = @EmpTransferState
        and FederalStatus = coalesce(@EmpFederalFilingStatus,' ')
    );
    

    或者直接从查询中加入它,而不是调用函数。

    【讨论】:

    • 我试图掌握用户定义函数的窍门,因为我对它们不太了解。程序我理解的比较清楚。为了将查询与函数连接起来,它是否会是“从 EmployeeTransfers 中选择 EmpFederalFilingStatus = @EmpFederalFilingStatus 和 StateFilingStatus = StateFilingStatus”
    猜你喜欢
    • 2014-04-10
    • 2016-10-14
    • 2016-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-03
    • 2019-11-27
    相关资源
    最近更新 更多