【问题标题】:PL/SQL Group By - ORA-01422: exact fetch returns more than requested number of rowsPL/SQL 分组依据 - ORA-01422:精确提取返回的行数多于请求的行数
【发布时间】:2013-08-30 22:14:47
【问题描述】:

我正在编写以下查询,我想显示汽车注册、汽车组名称、型号名称、成本和每辆车的预订数量。我必须使用显式游标,并且必须使用隐式游标来计算属于每辆车的预订数量。

我的查询如下:

    SET SERVEROUTPUT ON FORMAT WRAP SIZE 12000
Declare
v_count number;
cursor carcur IS
SELECT * FROM i_car;
v_car carcur%ROWTYPE;
Begin
Select COUNT (registration)
INTO v_count
from i_booking
group by registration;
FOR v_car IN carcur LOOP
DBMS_OUTPUT.PUT_LINE('Registration:'|| '  '|| v_car.registration);
DBMS_OUTPUT.PUT_LINE('Car Group:'|| ' ' ||v_car.car_group_name);
DBMS_OUTPUT.PUT_LINE('Model Name:'|| ' '||v_car.model_name);
DBMS_OUTPUT.PUT_LINE('Cost:'|| ' '||v_car.cost);
DBMS_OUTPUT.PUT_LINE('Total Bookings:'|| ' '||v_count);
DBMS_OUTPUT.NEW_LINE;

END LOOP;
End;

我得到的输出如下: 宣布 * 第 1 行的错误: ORA-01422: 精确提取返回的行数多于请求的行数 ORA-06512: 在第 7 行

我确信这与将返回值放入变量中有关,但我不知道如何纠正这一点。

任何建议将不胜感激。

非常感谢。

【问题讨论】:

    标签: sql oracle plsql oracle11g oracle10g


    【解决方案1】:

    错误出现在group by 子句中。你得到了count(registration) 的多行,因为你在上面使用了group by。目前的临时解决方案是删除group by 子句。

    【讨论】:

      【解决方案2】:

      这对我有用。我将隐式 SELECT 语句移动到循环游标中并添加了一个 WHERE 子句,说 WHERE registration = v_car.registration;

      SET SERVEROUTPUT ON FORMAT WRAP SIZE 12000
          Declare
          v_count number;
          cursor carcur IS
          SELECT * FROM i_car;
          v_car carcur%ROWTYPE;
          Begin
          FOR v_car IN carcur LOOP
          Select COUNT (registration)
          INTO v_count
          from i_booking
          WHERE registration = v_car.registration;
          DBMS_OUTPUT.PUT_LINE('Registration:'|| '  '|| v_car.registration);
          DBMS_OUTPUT.PUT_LINE('Car Group:'|| ' ' ||v_car.car_group_name);
          DBMS_OUTPUT.PUT_LINE('Model Name:'|| ' '||v_car.model_name);
          DBMS_OUTPUT.PUT_LINE('Cost:'|| ' '||v_car.cost);
          DBMS_OUTPUT.PUT_LINE('Total Bookings:'|| ' '||v_count);
          DBMS_OUTPUT.NEW_LINE;
          END LOOP;
          End;
      

      非常感谢大家的帮助。

      【讨论】:

        【解决方案3】:

        由于您将其返回到单个变量v_count时,从SELECT COUNT(注册)返回超过一个值时会发生错误。

        如果您尝试为各种注册选择所有计数,您需要为 v_count 使用数组类型,如下所示:

        declare
        v_count number;
        v_counts is table of v_count
        
        Begin
            Select COUNT (registration)
            bulk collect INTO v_counts
            from i_booking
        group by registration;
        
        if (v_counts > 0) then
           for i in v_counts.first..last loop
            <do your printing>
           end loop;
        end if;
        end;
        /
        

        我还添加了一个使用批量收集的优化,因为这会给您带来稍快的性能。

        【讨论】:

        【解决方案4】:

        您面临的错误是因为您试图将多个值分配给单个值变量。

        您的查询返回多个值主要是因为您使用的是group bygroup by 所做的是,在您的情况下,为该列中的每个不同值查找列 registration 中的值的总数。

        假设,让我们看一个例子-

        registration | other columns ...
        1            | ...
        1            | ...
        1            | ...
        2            | ...
        3            | ...
        3            | ...
        

        因此使用group by 查询的输出将是

        registration | count(registration)
        1            | 3
        2            | 1
        3            | 2
        

        请注意,registration 列未在您的 select 列表中选择,仅选择了 count(registration),根据示例可以包含多个值。

        因此现在有三种情况-

        1. 如果以上是您想要的输出,那么上面 clieu 的回答很有用。

        2. 如果您只想获取registration 列中所有非空值的计数,只需删除group by 子句即可。

        3. 如果要计算registration 列中所有DISTINCT 非空值的计数,可以使用count(distinct registration) 并删除group by,如下所示:

          SET SERVEROUTPUT ON FORMAT WRAP SIZE 12000
          Declare
          v_count number;
          cursor carcur IS
          SELECT * FROM i_car;
          v_car carcur%ROWTYPE;
          Begin
          Select COUNT (DISTINCT registration)
          INTO v_count
          from i_booking;
          FOR v_car IN carcur LOOP
          DBMS_OUTPUT.PUT_LINE('Registration:'|| '  '|| v_car.registration);
          DBMS_OUTPUT.PUT_LINE('Car Group:'|| ' ' ||v_car.car_group_name);
          DBMS_OUTPUT.PUT_LINE('Model Name:'|| ' '||v_car.model_name);
          DBMS_OUTPUT.PUT_LINE('Cost:'|| ' '||v_car.cost);
          DBMS_OUTPUT.PUT_LINE('Total Bookings:'|| ' '||v_count);
          DBMS_OUTPUT.NEW_LINE;
          
          END LOOP;
          End;
          /
          

        【讨论】:

        • 我将我的 inplicid 光标包含在 For 循环中,并添加了一个 WHERE 子句,说明 WHERE registration = v_car.registration。那成功了。感谢您的回复。
        猜你喜欢
        • 1970-01-01
        • 2016-11-29
        • 2013-11-15
        • 2019-01-27
        • 2015-09-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多