gpt4 book ai didi

oracle - TOO_MANY_ROWS 引发,但变量仍然获得一个值

转载 作者:行者123 更新时间:2023-12-04 13:42:38 28 4
gpt4 key购买 nike

我刚刚发现,如果您有一个引发 TOO_MANY_ROWS 异常的 SELECT INTO,该变量仍会从查询检索到的第一条记录中分配值。这是预期的行为吗?

这是我的例子:

for co in my_cursor loop
l_sco_db_id := null;

begin
select db_id
into l_sco_db_id
from objects_tab
where object_name = co.object_name;

exception
when no_data_found then
dbms_output.put_line('No objects_tab record found for Object ' || co.object_name);
when too_many_rows then
dbms_output.put_line('Multiple objects_tab records found for Object ' || co.object_name);
l_sco_db_id := null;
end;
end loop;

这是在一个循环内,所以我在开始时将变量设置为 null 以确保它是空白的,但是我不得不在 WHEN TOO_MANY_ROWS 异常中再次明确地这样做,这是我没想到的。我的同事(至少,那些直接听到的)也没有期望这个变量有一个值。

最佳答案

这是预期的行为,因为当你了解幕后发生的事情时,它是有道理的。但当你第一次看到它时,这绝对是一种看起来很奇怪的行为。从技术上讲,该行为被记录为未定义,因此不应依赖它,并且将来可能会发生变化。

在封面下,一个 select into只是语法糖

  • 打开光标
  • 从游标中取出一行到目标变量
  • 扔一个 no_data_found如果未获取任何行,则异常
  • 尝试从游标中获取第二行,抛出 too_many_rows如果第二次获取成功,则异常。

  • 鉴于此,目标变量将在第一次获取时写入是有道理的。 select into statement 的 Oracle 文档然而,指出

    PL/SQL raises the predefined exception TOO_MANY_ROWS and the values of the variables in the INTO clause are undefined.



    因此,Oracle 可以自由地保持该值不变,或者让变量具有获取的第一行或第二行的值,或者实际上是其他任何值。而且您不应该编写依赖于任何特定行为的代码。

    例如,如果您查看 this blog post from Jeff Kemp ,该变量采用获取的第一行中的值。但是如果你对 Jeff 的代码做一个小的调整,这样你就可以获取一个局部变量
    CREATE or replace PROCEDURE proc2 (v OUT NUMBER) IS
    l_v integer;
    BEGIN
    SELECT 1 INTO l_v FROM all_objects;
    EXCEPTION
    WHEN TOO_MANY_ROWS THEN
    dbms_output.put_line
    ('TOO MANY ROWS: v='
    || l_v);
    v := l_v;
    END;
    /

    然后行为会发生变化并且该值似乎不会被覆盖。
    DECLARE
    v NUMBER;
    BEGIN
    proc2(v);
    dbms_output.put_line('AFTER: v=' || v);
    END;
    /

    关于oracle - TOO_MANY_ROWS 引发,但变量仍然获得一个值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40138984/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com