包以失败状态结束。 ORA-00937 没那么容易

Posted

技术标签:

【中文标题】包以失败状态结束。 ORA-00937 没那么容易【英文标题】:The package ends with a failed status. ORA-00937 not so easy 【发布时间】:2021-12-23 11:48:57 【问题描述】:

PS 提供的答案没有帮助。错误仍然存​​在。如果有人仍然可以提供帮助,需要帮助:)

美好的一天。包编译成功,当我通过作业调用它时,我得到失败状态和错误

"ORA-00937: 不是单组群函数 ORA-06512: 在 “DMA.FILL_F101_ROUND_F”,第 42 行 ORA-06512:第 2 行“

提示我粗心,我在非组参数上使用了group by,但错误并没有消失。我了解在选择中使用组聚合器时,有必要在组中指明不是组聚合器。但最终调用包时它不起作用。我阅读了类似的问题,并且建议在任何地方重新考虑 group by。我似乎已经使用了所有可能的选项,但没有帮助。 提前致谢!

 group by
       trunc(i_OnDate, 'mm'),
       last_day(i_OnDate),
       s.chapter,
       substr(acc_d.account_number, 1, 5),
       acc_d.char_type;

我的 pck:

    create or replace package body dma.fill_f101_round_f is

  ----------------------------------------------------------------------------------------------------
  procedure "$Rev: 220707 $"                 is begin null; end;
  procedure "$URL:: https://svn.neoflex.ru$" is begin null; end;
  procedure "$Author:: rbubnov $"            is begin null; end;
  procedure "$Date:: 2018-12-22 12:09:59 #$" is begin null; end;

  ----------------------------------------------------------------------------------------------------
  procedure Log
  ( i_message                      in varchar2
  ) 
  is
  begin
    dma.logger.writeLog('[' || c_MartName || '] ' || i_message);
  end;
  ----------------------------------------------------------------------------------------------------

  ----------------------------------------------------------------------------------------------------
  procedure fill
  ( i_OnDate                       in date
  )
  is
  begin

    Log( '[BEGIN] fill(i_OnDate => date ''' 
         || to_char(i_OnDate, 'yyyy-mm-dd') 
         || ''');'
       );
    
    Log( 'delete on_date = ' 
         || to_char(i_OnDate, 'yyyy-mm-dd')
       );

    delete
      from dma.DM_F101_ROUND_F f
     where trunc(i_OnDate, 'mm')  =  from_date
       and last_day(i_OnDate)    =  to_date;
   
    Log('insert');
   
    insert 
      into dma.dm_f101_round_f f
           ( from_date         
           , to_date           
           , chapter           
           , ledger_account    
           , characteristic    
           , balance_in_rub    
           , balance_in_val    
           , balance_in_total  
           , turn_deb_rub      
           , turn_deb_val      
           , turn_deb_total    
           , turn_cre_rub      
           , turn_cre_val      
           , turn_cre_total    
           , balance_out_rub  
           , balance_out_val   
           , balance_out_total 
           )
    select 
           trunc(i_OnDate, 'mm')                 as from_date,
           last_day(i_OnDate)                    as to_date,
           s.chapter                             as chapter,
           substr(acc_d.account_number, 1, 5)    as ledger_account,
           acc_d.char_type                       as characteristic,
           -- RUB balance
           sum( case 
                  when cur.currency_code in ('643', '810')
                  then b.balance_out
                  else 0
                 end
              )                                  as balance_in_rub,
          -- VAL balance converted to rub
          sum( case 
                 when cur.currency_code not in ('643', '810')
                 then b.balance_out * exch_r.reduced_cource
                 else 0
                end
             )                                   as balance_in_val,
          -- Total: RUB balance + VAL converted to rub
          sum(  case 
                 when cur.currency_code in ('643', '810')
                 then b.balance_out
                 else b.balance_out * exch_r.reduced_cource
               end
             )                                   as balance_in_total  ,
           -- RUB debet turnover
           sum(case 
                 when cur.currency_code in ('643', '810')
                 then at.debet_amount_rub
                 else 0
               end
           )                                     as turn_deb_rub,
           -- VAL debet turnover converted
           sum(case 
                 when cur.currency_code not in ('643', '810')
                 then at.debet_amount_rub
                 else 0
               end
           )                                     as turn_deb_val,
           -- SUM = RUB debet turnover + VAL debet turnover converted
           sum(at.debet_amount_rub)              as turn_deb_total,
           -- RUB credit turnover
           sum(case 
                 when cur.currency_code in ('643', '810')
                 then at.credit_amount_rub
                 else 0
               end
              )                                  as turn_cre_rub,
           -- VAL credit turnover converted
           sum(case 
                 when cur.currency_code not in ('643', '810')
                 then at.credit_amount_rub
                 else 0
               end
              )                                  as turn_cre_val,
           -- SUM = RUB credit turnover + VAL credit turnover converted
           sum(at.credit_amount_rub)             as turn_cre_total,
           
           sum( case 
                 when cur.currency_code     in ('643','810') and acc_d.char_type = 'A'
                 then
                       sum(case 
                              when cur.currency_code in ('643', '810')
                              then b.balance_out
                              else 0
                             end
                          ) -
                       sum(case 
                             when cur.currency_code in ('643', '810')
                             then at.credit_amount_rub
                             else 0
                           end
                          ) +
                       sum(case 
                             when cur.currency_code in ('643', '810')
                             then at.debet_amount_rub
                             else 0
                           end
                       )
                 
                 when cur.currency_code     in ('643','810') and acc_d.char_type = 'P'
                 then 
                        sum(case 
                              when cur.currency_code in ('643', '810')
                              then b.balance_out
                              else 0
                             end
                          ) +
                       sum(case 
                             when cur.currency_code in ('643', '810')
                             then at.credit_amount_rub
                             else 0
                           end
                          ) -
                       sum(case 
                             when cur.currency_code in ('643', '810')
                             then at.debet_amount_rub
                             else 0
                           end
                       )

                 else 0
                end
             )                                                          as balance_out_rub,
             
             
          sum(  case 
                 when cur.currency_code not in ('643', '810') and acc_d.char_type = 'A'
                 then
                 
                      sum(  case 
                             when cur.currency_code not in ('643', '810')
                             then b.balance_out * exch_r.reduced_cource
                             else 0
                            end
                         ) -
                      sum(  case 
                             when cur.currency_code not in ('643', '810')
                             then at.credit_amount_rub
                             else 0
                           end
                         ) + 
                      sum(  case 
                             when cur.currency_code not in ('643', '810')
                             then at.debet_amount_rub
                             else 0
                           end
                         )
                 
                 when cur.currency_code not in ('643', '810') and acc_d.char_type = 'P'
                 then 
                      sum(  case 
                             when cur.currency_code not in ('643', '810')
                             then b.balance_out * exch_r.reduced_cource
                             else 0
                            end
                         )+ 
                      sum(  case 
                             when cur.currency_code not in ('643', '810')
                             then at.credit_amount_rub
                             else 0
                           end
                         )- 
                      sum(  case 
                             when cur.currency_code not in ('643', '810')
                             then at.debet_amount_rub
                             else 0
                           end
                         )
                 else 0
               end
             )                                                as balance_out_val,
             cast(null as number)                             as balance_out_total 
      from ds.md_ledger_account_s s
      join ds.md_account_d acc_d
        on substr(acc_d.account_number, 1, 5) = s.ledger_account
      join ds.md_currency_d cur
        on cur.currency_rk = acc_d.currency_rk
      left 
      join ds.ft_balance_f b
        on b.account_rk = acc_d.account_rk
       and b.on_date  = trunc(i_OnDate, 'mm') - 1
      left 
      join ds.md_exchange_rate_d exch_r
        on exch_r.currency_rk = acc_d.currency_rk
       and i_OnDate between exch_r.data_actual_date and exch_r.data_actual_end_date
      left 
      join dma.dm_account_turnover_f at
        on at.account_rk = acc_d.account_rk
       and at.on_date between trunc(i_OnDate, 'mm') and last_day(i_Ondate)
     where i_OnDate between s.start_date and s.end_date
       and i_OnDate between acc_d.data_actual_date and acc_d.data_actual_end_date
       and i_OnDate between cur.data_actual_date and cur.data_actual_end_date
    group by
       trunc(i_OnDate, 'mm'),
       last_day(i_OnDate),
       s.chapter,
       substr(acc_d.account_number, 1, 5),
       acc_d.char_type;
    update dm_f101_round_f f set
           f.balance_out_total = f.balance_out_val  + f.balance_out_rub;

    Log('[END] inserted ' || to_char(sql%rowcount) || ' rows.');

    commit;
    
  end;
  ----------------------------------------------------------------------------------------------------

end fill_f101_round_f;
/```



【问题讨论】:

与您的问题无关,但procedure "$Rev: 220707 $" is begin null; end; 是否更适合function revision return varchar2 is begin return '$Rev: 220707 $'; end; 表定义会有很大帮助。 【参考方案1】:

您错过了分组中的一些列。你也在总结一个总和,这让事情变得更加棘手。也就是说,总和的逻辑取决于您已经分组的列之一,因此您可以简化:

acc_d.char_type,
sum( case 
      when cur.currency_code     in ('643','810') and acc_d.char_type = 'A'
      then
            sum(case 
                   when cur.currency_code in ('643', '810')
                   then b.balance_out
                   else 0
                  end
               ) -
            sum(case 
                  when cur.currency_code in ('643', '810')
                  then at.credit_amount_rub
                  else 0
                end
               ) +
            sum(case 
                  when cur.currency_code in ('643', '810')
                  then at.debet_amount_rub
                  else 0
                end
            )
      
      when cur.currency_code     in ('643','810') and acc_d.char_type = 'P'
      then 
             sum(case 
                   when cur.currency_code in ('643', '810')
                   then b.balance_out
                   else 0
                  end
               ) +
            sum(case 
                  when cur.currency_code in ('643', '810')
                  then at.credit_amount_rub
                  else 0
                end
               ) -
            sum(case 
                  when cur.currency_code in ('643', '810')
                  then at.debet_amount_rub
                  else 0
                end
            )

      else 0
     end
  )                                                          as balance_out_rub
...
group by acc_d.char_type...

可以变成

acc_d.char_type,
case when acc_d.char_type = 'A'
  then
        sum(case 
               when cur.currency_code in ('643', '810')
               then b.balance_out
               else 0
              end
           ) -
        sum(case 
              when cur.currency_code in ('643', '810')
              then at.credit_amount_rub
              else 0
            end
           ) +
        sum(case 
              when cur.currency_code in ('643', '810')
              then at.debet_amount_rub
              else 0
            end
        )
  
  when acc_d.char_type = 'P'
  then 
         sum(case 
               when cur.currency_code in ('643', '810')
               then b.balance_out
               else 0
              end
           ) +
        sum(case 
              when cur.currency_code in ('643', '810')
              then at.credit_amount_rub
              else 0
            end
           ) -
        sum(case 
              when cur.currency_code in ('643', '810')
              then at.debet_amount_rub
              else 0
            end
        )
  
  else 0
end as balance_out_rub
...
group by acc_d.char_type...

当然,你可以进一步简化它。

【讨论】:

【参考方案2】:

所有非聚合列必须包含在group by 子句中,而不仅仅是其中的一部分。

目前,这里是select

 select      
       trunc(i_OnDate, 'mm')                 as from_date,
       last_day(i_OnDate)                    as to_date,
       s.chapter                             as chapter,
       substr(acc_d.account_number, 1, 5)    as ledger_account,
       acc_d.char_type                       as characteristic
       

这是group by:

 group by 
       s.chapter,
       substr(acc_d.account_number, 1, 5),
       acc_d.char_type
       

应该是

 group by
       trunc(i_OnDate, 'mm'),
       last_day(i_OnDate),
       s.chapter,
       substr(acc_d.account_number, 1, 5),
       acc_d.char_type

【讨论】:

我已经试过了,可惜没用,调用包的时候报错也是一样。

以上是关于包以失败状态结束。 ORA-00937 没那么容易的主要内容,如果未能解决你的问题,请参考以下文章

错误:ORA-00937

ORA-00937: 不是单组组函数错误

sql - ORA-00937: 不是单组组函数

Oracle SQL:ORA-00937:不是单组组函数

ORA-00937: 不是 oracle 中的单组组函数

关于如何克服 ORA-00937 的任何建议?