【问题标题】:PL/SQL Fetches more than requested number of rowsPL/SQL 获取多于请求的行数
【发布时间】:2023-04-09 08:25:01
【问题描述】:

我收到此错误,但我不知道如何解决它..

声明
*
第 1 行出现错误:
ORA-01422: 精确提取返回的行数多于请求的行数
ORA-06512: 在第 7 行

这是我的代码,它必须计算 SQL 语句的输出并打印数字,但它不起作用

sqlplus -S "/ as sysdba " <<EOF > /home/oracle/testDaten/Ausgabe.log
set verify off;
set serveroutput on;
set lines 12345 pages 12345;

DECLARE

cnt NUMBER(10);

BEGIN

select count(v.name) into cnt
  from cdb_objects c, v\$containers v
 where object_type like '%JAVA%'
   and c.con_id = v.con_id
   and owner not in ('MDSYS', 'OJVMSYS')
   and c.con_id != 1
   group by v.name
    having count(*) > (select count(*) from cdb_objects c2 
                where object_type like '%JAVA%' 
                and c2.con_id = 1 
                and owner not in ('MDSYS', 'OJVMSYS'));
    

    DBMS_Output.put_line(cnt);
 
end;
/
EXIT
EOF

【问题讨论】:

  • 这里为什么要使用 group by 子句?

标签: sql oracle plsql


【解决方案1】:

在 PL/SQL 中,对变量的裸 SELECT 必须恰好返回一行。如果它返回零行,您将收到 ORA-01403(未找到数据)异常,如果它返回多于一行,您将收到 ORA-01422(精确提取返回超过请求的行数)错误.

问题是您的查询将返回多行,因为与v$containers 连接。

解决方案很简单:使用游标循环遍历各个记录并逐一打印。

BEGIN
  for rec in (
    select v.name, count(v.name) cnt
      from cdb_objects c, v$containers v
     where object_type like '%JAVA%'
       and c.con_id = v.con_id
       and owner not in ('MDSYS', 'OJVMSYS')
       and c.con_id != 1
       group by v.name
        having count(*) > (select count(*) from cdb_objects c2 
                    where object_type like '%JAVA%' 
                    and c2.con_id = 1 
                    and owner not in ('MDSYS', 'OJVMSYS'))
  )loop
    dbms_output.put_line(rec.name || ': ' || rec.cnt);
  end loop; 
end;
/

这里用for rec in ( ... ) loop ... end loop;包围查询 该记录是隐式定义的,您可以将其命名为任何名称(我使用了rec)。

在循环中引用返回的列,就像使用记录变量表列一样。

一些不错的副作用:

  • 您现在不需要声明 count 变量,因为它是隐式记录的一部分。
  • 无需打开、获取和关闭游标,这一切都为您完成。
  • 永远不会发生“未找到数据”的情况;如果没有匹配的记录,循环将不会循环。

【讨论】:

    【解决方案2】:

    您的 GROUP BY 子句是这里的罪魁祸首。只要摆脱,你就可以开始了 -

    DECLARE
    cnt NUMBER(10);
    
    BEGIN
    
         SELECT count(v.name)
           INTO cnt
           FROM cdb_objects c, v\$containers v
          WHERE object_type like '%JAVA%'
            AND c.con_id = v.con_id
            AND owner NOT IN ('MDSYS', 'OJVMSYS')
            AND c.con_id != 1
          -- group by v.name
          -- HAVING count(*) > (SELECT count(*)
          --                    FROM cdb_objects c2 
          --                   WHERE object_type LIKE '%JAVA%'
          --                     AND c2.con_id = 1
          --                     AND owner NOT IN ('MDSYS', 'OJVMSYS'));
    
        DBMS_Output.put_line(cnt);
    
    end;
    /
    

    如果您真的想使用它,请分享您的预期结果。

    【讨论】:

    • 我想选择所有对象比其他数据库更多的数据库。像这样:数据库 1 有 10 个 java 对象,数据库 2 和 3 有 13 个 java 对象,所以他必须向我展示数据库 2 和3 so (count = 2) 这就是为什么我将它们分组为有
    • 你想要拥有最多对象的所有者(数据库)吗?
    • 没有我正在处理具有多个数据库的多租户数据库,这就是为什么我加入 v$containers 这给了我数据库的名称所以例如有一个容器数据库 CDB$ROOT
    猜你喜欢
    • 2013-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-15
    • 2018-01-15
    • 1970-01-01
    相关资源
    最近更新 更多