具有嵌套 CASES 的 Sql 标量值函数

Posted

技术标签:

【中文标题】具有嵌套 CASES 的 Sql 标量值函数【英文标题】:Sql Scalar valued Function with nested CASES 【发布时间】:2016-09-08 16:22:04 【问题描述】:

我需要帮助来更正下面的语法,嵌套的 case 包含将值返回给在另一个 CASE 中评估的变量的函数。

    CREATE FUNCTION dbo.EpsClassificacaoConjunto (@Bloco varchar(5), @Sub varchar(5), @SSub varchar(5))
RETURNS varchar(5)
  AS
  BEGIN
    DECLARE @Comprimento float = CASE WHEN @Sub is null AND @SSub not null then SELECT dbo.EpsComprimentoSub(DimensaoDePerfil) FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem is null AND Subsubmontagem=@SSub AND Tipo='SET'
                                      WHEN @SSub is null and @Sub not null then SELECT dbo.EpsComprimentoSub(DimensaoDePerfil) FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem=@Sub AND Subsubmontagem is null AND Tipo='SET'
                                      ELSE SELECT dbo.EpsComprimentoSub(DimensaoDePerfil) FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem=@Sub AND Subsubmontagem=@SSub AND Tipo='SET' END;

    DECLARE @Largura float = CASE WHEN @Sub is null AND @SSub not null then SELECT dbo.EpsLarguraSub(DimensaoDePerfil) FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem is null AND Subsubmontagem=@SSub AND Tipo='SET'
                                  WHEN @SSub is null and @Sub not null then SELECT dbo.EpsLarguraSub(DimensaoDePerfil) FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem=@Sub AND Subsubmontagem is null AND Tipo='SET'
                                  ELSE SELECT dbo.EpsLarguraSub(DimensaoDePerfil) FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem=@Sub AND Subsubmontagem=@SSub AND Tipo='SET' END;

    DECLARE @Altura float = CASE WHEN @Sub is null AND @SSub not null then SELECT dbo.EpsAlturaSub(DimensaoDePerfil) FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem is null AND Subsubmontagem=@SSub AND Tipo='SET'
                                 WHEN @SSub is null and @Sub not null then SELECT dbo.EpsAlturaSub(DimensaoDePerfil) FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem=@Sub AND Subsubmontagem is null AND Tipo='SET'
                                 ELSE SELECT dbo.EpsAlturaSub(DimensaoDePerfil) FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem=@Sub AND Subsubmontagem=@SSub AND Tipo='SET' END;


    DECLARE @Peso float = CASE WHEN @Sub is null and @SSub is not null then SELECT Peso FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem is null AND Subsubmontagem=@SSub AND Tipo='SET'
                               WHEN @Sub not null and @SSub is null then SELECT Peso FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem=@Sub AND Subsubmontagem is null AND Tipo='SET'
                               ELSE SELECT Peso FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem=@Sub AND Subsubmontagem=@SSub AND Tipo='SET' END;

    DECLARE @Pagamento varchar(2) = CASE WHEN @Sub is null and @SSub not null then SELECT TOP 1 CodigoDeFabricacao FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem is null AND Subsubmontagem=@SSub AND Tipo='SET'
                                         WHEN @Sub not null and @SSub is null then SELECT TOP 1 CodigoDeFabricacao FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem=@Sub AND Subsubmontagem is null AND Tipo='SET'
                                         ELSE SELECT TOP 1 CodigoDeFabricacao FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem=@Sub AND Subsubmontagem=@SSub AND Tipo='SET' END;

    DECLARE @Fabricacao varchar(2) = CASE WHEN @Sub is null and @SSub not null then SELECT TOP 1 CodigoDeFabricacao FROM VShiPartBom WHERE Bloco=@Bloco AND Submontagem is null AND Subsubmontagem=@SSub AND Tipo='SET'
                                          WHEN @Sub not null and @SSub is null then SELECT TOP 1 CodigoDeFabricacao FROM VShiPartBom WHERE Bloco=@Bloco AND Submontagem=@Sub AND Subsubmontagem is null AND Tipo='SET'
                                          ELSE SELECT TOP 1 CodigoDeFabricacao FROM VShiPartBom WHERE Bloco=@Bloco AND Submontagem=@Sub AND Subsubmontagem=@SSub AND Tipo='SET' END;

    RETURN CASE WHEN @Peso<5000 AND @Largura<2500 AND @Altura<4000 AND @Comprimento<10000 THEN '1-B'
                WHEN @Peso<5000 AND @Largura<5000 AND @Altura<4000 AND @Comprimento<10000 THEN '1-A'
                WHEN @Peso<10000 AND @Largura<10000 AND @Altura<4000 AND @Comprimento<10000 THEN '2'
                WHEN @Peso<5000 AND @Largura<2500 AND @Altura<4000 AND @Comprimento>=10000 AND @Comprimento<15000 THEN '3'
                ELSE 'ESP' END

  END
GO

逻辑部分已经描述过了,但是,我的sql语法似乎有问题,请指教...

【问题讨论】:

您是否仔细阅读了错误消息并尝试找到它们? 这是错误:'1 文本中有错误或对象的类型与此文档不对应。 ...' 你用的是什么关系型数据库? MSSQL 2008 版本 当你在 SSMS 中解析这个查询时,你会得到特定行的特定错误。 【参考方案1】:

我在 MS SQL Server Management Studio 中对其进行了调试,并且运行良好:

    CREATE FUNCTION EpsClassificacaoConjunto 
(
    -- Add the parameters for the function here
    @Bloco varchar(5),
    @Sub varchar(5),
    @SSub varchar(5)
)
RETURNS varchar(5)
AS
BEGIN
    -- Declare the return variable here
    DECLARE @Result varchar(5)
    DECLARE @Comprimento float;
    DECLARE @Largura float;
    DECLARE @Altura float;
    DECLARE @Peso float;
    DECLARE @Pagamento varchar(2);
    DECLARE @Fabricacao varchar(2);

    -- Add the T-SQL statements to compute the return value here
    SELECT @Comprimento =  CASE WHEN (@Sub is null AND @SSub is not null) then (SELECT dbo.EpsComprimentoSub(DimensaoDePerfil) FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem is null AND Subsubmontagem=@SSub AND Tipo='SET')
                                WHEN (@SSub is null and @Sub is not null) then (SELECT dbo.EpsComprimentoSub(DimensaoDePerfil) FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem=@Sub AND Subsubmontagem is null AND Tipo='SET')
                                ELSE (SELECT dbo.EpsComprimentoSub(DimensaoDePerfil) FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem=@Sub AND Subsubmontagem=@SSub AND Tipo='SET') END;

    SELECT @Largura = CASE WHEN (@Sub is null AND @SSub is not null) then (SELECT dbo.EpsLarguraSub(DimensaoDePerfil) FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem is null AND Subsubmontagem=@SSub AND Tipo='SET')
                            WHEN (@SSub is null and @Sub is not null) then (SELECT dbo.EpsLarguraSub(DimensaoDePerfil) FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem=@Sub AND Subsubmontagem is null AND Tipo='SET')
                            ELSE (SELECT dbo.EpsLarguraSub(DimensaoDePerfil) FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem=@Sub AND Subsubmontagem=@SSub AND Tipo='SET') END;


      SELECT @Altura = CASE WHEN (@Sub is null AND @SSub is not null) then (SELECT dbo.EpsAlturaSub(DimensaoDePerfil) FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem is null AND Subsubmontagem=@SSub AND Tipo='SET')
                                 WHEN (@SSub is null and @Sub is not null) then (SELECT dbo.EpsAlturaSub(DimensaoDePerfil) FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem=@Sub AND Subsubmontagem is null AND Tipo='SET')
                                 ELSE (SELECT dbo.EpsAlturaSub(DimensaoDePerfil) FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem=@Sub AND Subsubmontagem=@SSub AND Tipo='SET') END;



      SELECT @Peso = CASE WHEN (@Sub is null and @SSub is not null) then (SELECT Peso FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem is null AND Subsubmontagem=@SSub AND Tipo='SET')
                               WHEN (@Sub is not null and @SSub is null) then (SELECT Peso FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem=@Sub AND Subsubmontagem is null AND Tipo='SET')
                               ELSE (SELECT Peso FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem=@Sub AND Subsubmontagem=@SSub AND Tipo='SET') END;


      SELECT @Pagamento = CASE WHEN (@Sub is null and @SSub is not null) then (SELECT TOP 1 CodigoDeFabricacao FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem is null AND Subsubmontagem=@SSub AND Tipo='SET')
                                         WHEN (@Sub is not null and @SSub is null) then (SELECT TOP 1 CodigoDeFabricacao FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem=@Sub AND Subsubmontagem is null AND Tipo='SET')
                                         ELSE (SELECT TOP 1 CodigoDeFabricacao FROM VShiAssemblyBom WHERE Bloco=@Bloco AND Submontagem=@Sub AND Subsubmontagem=@SSub AND Tipo='SET') END;


      SELECT @Fabricacao = CASE WHEN (@Sub is null and @SSub is not null) then (SELECT TOP 1 CodigoDeFabricacao FROM VShiPartBom WHERE [Bloco Orig.]=@Bloco AND Submontagem is null AND Subsubmontagem=@SSub AND Tipo='SET')
                                          WHEN (@Sub is not null and @SSub is null) then (SELECT TOP 1 CodigoDeFabricacao FROM VShiPartBom WHERE [Bloco Orig.]=@Bloco AND Submontagem=@Sub AND Subsubmontagem is null AND Tipo='SET')
                                          ELSE (SELECT TOP 1 CodigoDeFabricacao FROM VShiPartBom WHERE [Bloco Orig.]=@Bloco AND Submontagem=@Sub AND Subsubmontagem=@SSub AND Tipo='SET') END;

    SELECT @Result = CASE WHEN @Peso<5000 AND @Largura<2500 AND @Altura<4000 AND @Comprimento<10000 THEN '1-B'
                            WHEN @Peso<5000 AND @Largura<5000 AND @Altura<4000 AND @Comprimento<10000 THEN '1-A'
                            WHEN @Peso<10000 AND @Largura<10000 AND @Altura<4000 AND @Comprimento<10000 THEN '2'
                            WHEN @Peso<5000 AND @Largura<2500 AND @Altura<4000 AND @Comprimento>=10000 AND @Comprimento<15000 THEN '3'
                            ELSE 'ESP' END

    -- Return the result of the function
    RETURN @Result

END
GO

【讨论】:

以上是关于具有嵌套 CASES 的 Sql 标量值函数的主要内容,如果未能解决你的问题,请参考以下文章

具有标量值函数的可变长度 NVARCHAR

SQL 标量值函数

在 SQL 中调用标量值函数

为啥 SQL Server 标量值函数变慢?

sql [sql]标量值函数示例

sql标量值函数非常慢