导致此存储过程出错的原因是什么?

时间:2016-06-08 17:14:01

标签: sql-server stored-procedures

我有一个存储过程来处理每月的工作。存储过程将循环遍历所有可用作业,并在将其插入表格之前进行一些计算。大多数工作都没问题,但对于某些工作,会出现错误

  

子查询返回的值超过1。这是不允许的   子查询跟随=,!=,<,< =,>,> =或当子查询用作   表达。

以下是发生错误的部分:

IF EXISTS( SELECT *
              FROM aastocks  aastk
              WHERE aastk.estno = @lcEstno
            and 0 in (aastk.cartonratio1, 
                      aastk.cartonratio2, 
                      aastk.cartonratio3, 
                      aastk.cartonratio4, 
                      aastk.cartonratio5)
        )  EXECUTE ru_est_stocksum @lcEstNo

@lcEstNo在前面的代码中定义。

SET @lcEstno = (SELECT MAX(estno) FROM dbo.v_est_joblist WHERE ljob = @tcLjob)

MAX()应该只返回1个值,我不明白为什么会出现多值错误。

事实证明,错误的行号与存储过程中的行号不同。所以问题实际上存在于下面的代码中(在我注释掉下面的部分并且没有错误之后)。但我无法找出哪个子查询返回的值超过1。有什么想法吗?

INSERT INTO @JCDTotals
    SELECT  @tcLjob, coalesce(cast( ap.deptno as char(4)),'????') as deptno,
        CASE WHEN  coalesce(v_depuse_qty.DepUse, 1) = 1 THEN
                            CASE WHEN @tcCostBase = 'D' THEN CASE WHEN ap.procgroup = 'I' THEN aaprocqt.dmcstmat1 + aaprocqt.dmcstmat2 + aaprocqt.dmcstmat3 END
                                 WHEN @tcCostBase = 'A' THEN CASE WHEN ap.procgroup = 'I' THEN aaprocqt.costmats1 + aaprocqt.costmats2 + aaprocqt.costmats3 END
                                 ELSE ' 0 '
                             END
             ELSE 0     END AS ecostmats,
        CASE WHEN  coalesce(v_depuse_qty.DepUse, 1) = 1 THEN CASE WHEN @tcCostBase = 'D' THEN (1 / (1 + (ap.burden/100))) ELSE  1  END
                 * aaprocqt.costlab
             ELSE 0
             END        AS ecostlab,
        CASE WHEN coalesce(v_depuse_qty.DepUse, 1) = 1 THEN aaprocqt.proctime
             ELSE 0
             END        AS eprochours,
        0.0 AS bcostmats,
        0.0 AS bcostlab,
        0 AS bprochours,
        0.0 AS acostmats,
        0.0 AS acostlab,
        0 AS aprochours,
        0.0 AS chgcost,
        0 AS dirlab,
        0.0 AS aacost,
        0.0 AS pecost,
        0.0 AS otcost,
        0 AS sell
    FROM (
        SELECT  aaproces.idnumber,
            aaproces.estno,
            aaproces.procgroup,
            aaproces.partno,
                    aaproces.[lineno],
                    aaproces.counter,
            ssproces.burden,
            case WHEN aaproces.procgroup = 'I' then ssinvent.deptno
                     else ssproces.deptno end                   as deptno,
                case WHEN aaproces.procgroup = 'I' then ssinvent.matno
                     else STR(ssproces.procno,6) end                as procno,
            case WHEN aaproces.procgroup = 'I' then ssinvent.material
                     else ssproces.process end                  as process  
          FROM dbo.aaproces
            LEFT JOIN dbo.SSINVENT ON ssinvent.matno = aaproces.matno
                AND ssinvent.invtype IN ('G', 'I', 'F', 'S')
            LEFT JOIN dbo.SSPROCES ON ssproces.procno = aaproces.procno
          WHERE ((aaproces.procgroup = 'I' and ssinvent.deptno is not null)
            OR (aaproces.procgroup <> 'I' and ssproces.deptno is not null))
            AND ((aaproces.procgroup = 'I' and ssinvent.matno is not null)
            OR (aaproces.procgroup <> 'I' and ssproces.procno is not null))
        ) ap
        INNER join dbo.v_est_joblist
            on v_est_joblist.estno = ap.estno
        LEFT OUTER JOIN dbo.aaprocqt
            on aaprocqt.estno = ap.estno
            and ap.[lineno] = aaprocqt.[lineno]and aaprocqt.procgroup = ap.procgroup
            and ap.partno = aaprocqt.partno and ap.counter = aaprocqt.counter and aaprocqt.qty = v_est_joblist.alt
        LEFT OUTER JOIN dbo.v_depuse_qty
            ON v_est_joblist.estno = v_depuse_qty.estno
                AND v_depuse_qty.deptno = ap.deptno
                AND V_DEPUSE_QTY.LJOB = V_EST_JOBLIST.LJOB
                AND V_DEPUSE_QTY.ALT = V_EST_JOBLIST.ALT
    WHERE  v_est_joblist.ljob = @tcLjob
    --  AND  ssdept.divno like @lcDivNo
    --------------------------------------------------------------------------- PROCESS MATERIAL1,MATERIAL2,MATERIAL3 (ESTIMATED)
    UNION ALL
      SELECT @tcLjob, coalesce(ssinvent.deptno,'????') as deptno,
        CASE WHEN  coalesce((SELECT v_depuse_qty.DepUse FROM dbo.v_depuse_qty WHERE v_est_joblist.estno = v_depuse_qty.estno
                    AND ssinvent.deptno = v_depuse_qty.deptno
                    AND V_DEPUSE_QTY.LJOB = V_EST_JOBLIST.LJOB
                    AND V_DEPUSE_QTY.ALT = V_EST_JOBLIST.ALT), 1) = 1 THEN CASE     WHEN sq.CopyNum = 1 THEN CASE WHEN @tcCostBase = 'D' THEN aaprocqt.dmcstmat1 ELSE aaprocqt.costmats1 END
                                                    WHEN sq.CopyNum = 2 THEN CASE WHEN @tcCostBase = 'D' THEN aaprocqt.dmcstmat2 ELSE aaprocqt.costmats2 END
                                                    WHEN sq.CopyNum = 3 THEN CASE WHEN @tcCostBase = 'D' THEN aaprocqt.dmcstmat3 ELSE aaprocqt.costmats3 END
                                                    END
             ELSE 0
             END    AS ecostmats,
            0 AS ecostlab,
        0 AS eprochours,
        0 AS bcostmats,
        0 AS bcostlab,
        0 AS bprochours,
        0.0 AS acostmats,
        0.0 AS acostlab,
        0 AS aprochours,
        0.0 AS chgcost,
        0 AS dirlab,
        0.0 AS aacost,
        0.0 AS pecost,
        0.0 AS otcost,
        0 AS sell
      FROM dbo.aaproces JOIN dbo.v_est_joblist on v_est_joblist.estno = aaproces.estno
        CROSS JOIN @NumCopies sq
        LEFT JOIN dbo.ssproces on aaproces.procno = ssproces.procno
        LEFT JOIN dbo.ssinvent on ssinvent.matno = ( case   when sq.CopyNum = 1 then CASE WHEN aaproces.manmatno = ''  THEN ssproces.matno1 ELSE aaproces.manmatno  END
                                    when sq.CopyNum = 2 then CASE WHEN aaproces.manmatno2 = '' THEN ssproces.matno2 ELSE aaproces.manmatno2 END
                                    when sq.CopyNum = 3 then CASE WHEN aaproces.manmatno3 = '' THEN ssproces.matno3 ELSE aaproces.manmatno3 END
                                    end)
        JOIN dbo.aaprocqt on aaprocqt.estno = aaproces.estno and aaprocqt.procgroup = aaproces.procgroup
            and aaproces.partno = aaprocqt.partno and aaproces.[lineno] = aaprocqt.[lineno]
            and aaproces.counter = aaprocqt.counter and aaprocqt.qty = v_est_joblist.alt
      WHERE  aaproces.procgroup <> 'I'
         --and sq.CopyNum < 4
         and case   when sq.CopyNum = 1 then (manmatno  + matno1 )
            when sq.CopyNum = 2 then (aaproces.manmatno2 + ssproces.matno2 )
            when sq.CopyNum = 3 then (manmatno3 + matno3 )
            end <> ''
         AND v_est_joblist.ljob = @tcLjob
    --------------------------------------------------------------------------- STOCKS (ESTIMATED)
    UNION ALL
      SELECT @tcLjob, coalesce(case when aastocks.houvend = 'H' then ssinvent.deptno
                else case when aapthead.parttype = 'S' then @opt_stockccs
                          else @opt_stockccr end end,'????')
        as deptno,
        CASE WHEN  coalesce((SELECT v_depuse_qty.DepUse FROM dbo.v_depuse_qty WHERE v_est_joblist.estno = v_depuse_qty.estno
                    AND v_depuse_qty.deptno = ssdept.deptno
                    AND V_DEPUSE_QTY.LJOB = V_EST_JOBLIST.LJOB
                    AND V_DEPUSE_QTY.ALT = V_EST_JOBLIST.ALT), 1) = 1 THEN CASE WHEN @tcCostBase = 'D' THEN
                            CASE WHEN aastocks.houvend = 'V' THEN (1 / (1 + (ssdept.burden/100)))
                                   ELSE (1 / (1 + (ssinvent.burden/100))) END
                                ELSE  1  END  *
            case when v_est_joblist.alt = 1 then aastocks.stkcost1 * aastocks.cartonratio1
                     when v_est_joblist.alt = 2 then aastocks.stkcost2 * aastocks.cartonratio2
                     when v_est_joblist.alt = 3 then aastocks.stkcost3 * aastocks.cartonratio3
                     when v_est_joblist.alt = 4 then aastocks.stkcost4 * aastocks.cartonratio4
                     when v_est_joblist.alt = 5 then aastocks.stkcost5 * aastocks.cartonratio5
                 END
             ELSE 0
             END                AS ecostmats,
        0 as ecostlab,
        0 as eprochours,
        0 AS bcostmats,
        0 AS bcostlab,
        0 AS bprochours,
        0.0 AS acostmats,
        0.0 AS acostlab,
        0 AS aprochours,
        0.0 AS chgcost,
        0 AS dirlab,
        0.0 AS aacost,
        0.0 AS pecost,
        0.0 AS otcost,
        0 AS sell
    FROM dbo.aapthead
        INNER JOIN dbo.aastocks on aapthead.estno = aastocks.estno and aapthead.partno = aastocks.partno
        INNER JOIN dbo.v_est_joblist on v_est_joblist.estno = aapthead.estno
        LEFT OUTER JOIN dbo.ssinvent on aastocks.matno = ssinvent.matno
                AND ssinvent.invtype IN ('R', 'S')
        LEFT OUTER JOIN dbo.ssdept ON ssdept.deptno = (CASE WHEN aastocks.houvend = 'H' THEN ssinvent.deptno
                                     ELSE CASE WHEN aapthead.parttype = 'S' THEN @opt_stockccs
                                               ELSE  @opt_stockccr
                                   END
                             END)
    WHERE  v_est_joblist.ljob = @tcLjob
      AND  1 = [dbo].[DivisionCheck] (ssdept.divno,@tcDivNo)

2 个答案:

答案 0 :(得分:0)

在显示的三个代码示例中,我看不到任何会生成该子查询错误消息的内容。

  • exists()子查询旨在处理多个返回的行
  • select max()子查询格式正确
  • 如果第三个块中唯一的子查询返回多行
  • ,则没有任何内容会导致问题

因此,它必须是别的东西。我的猜测 - 这是一个猜测 - 在第三个bock中,表v_est_joblist和/或v_depuse_qty实际上是视图(我自己使用类似v_Blah约定的东西),其中一个出了问题。如果是这样,您需要测试这些视图,看看它们在加入主查询时返回的内容是什么。

答案 1 :(得分:-2)

您的“in”表达式似乎提供了多行值。因此,虽然“exists”可以接受多行作为输入,但是(aastk.cartonratio1,...)中的“0”不能。