【问题标题】:Execute immediate select returns no values执行立即选择不返回任何值
【发布时间】:2019-02-20 18:00:44
【问题描述】:

我有选择语句

select name, surname
from student
where id_student = 1;

返回

name surname
Bob Smith

我想创建具有相同选择语句的过程,使用立即执行:

create or replace procedure select_procedure
as
begin
execute immediate
'select name, surname
from student
where id_student = 1';
end;
/
exec select_procedure;

执行此过程时,它显示 PL/SQL 过程已成功完成。我如何得到结果? (设置服务器输出开启)

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    你必须选择进入的东西。如果您不这样做,则查询 isn't even executed(尽管已解析)。

    create or replace procedure select_procedure
    as
      l_name student.name%TYPE;
      l_surname student.name%TYPE;
    begin
      execute immediate
      'select name, surname
      from student
      where id_student = 1'
      into l_name, l_surname;
    end;
    /
    

    但是,没有特定的顺序: (a) 您应该使用绑定变量,而不是在动态语句中嵌入文字值 1; (b) 这根本不需要是动态的; (c) 调用者无论如何都无法看到查询返回的值 - 除非您改为选择 OUT 参数,或者使用 dbms_output() 显示它们(尽管这实际上应该只用于调试无法控制客户端是否显示)。

    所以你可以这样做:

    create or replace procedure select_procedure
    as
      l_name student.name%TYPE;
      l_surname student.name%TYPE;
    begin
      select name, surname
      into l_name, l_surname
      from student
      where id_student = 1;
    
      dbms_output.put_line('name=' || l_name ||', surname=' || l_surname);
    end;
    /
    

    create or replace procedure select_procedure (
      p_name OUT student.name%TYPE,
      p_surname OUT student.name%TYPE
    )
    as
    begin
      select name, surname
      into p_name, p_surname
      from student
      where id_student = 1;
    end;
    /
    

    并让你的调用者传入它自己的变量名来填充,然后对它们做任何需要的事情。调用者通常还会传入您要查找的 ID,因此您没有硬编码的 1。

    不过,过程似乎并不是最好的机制。

    此外,如果查询返回零行或多行,使用select ... into(静态或动态)将出错。仅当返回一行时才有效。游标可以处理任意数量的行 - 但除非您只是打印结果(如@Jayanth 所示),否则您需要将游标传回给调用者。您可以改为使用bulk collect into 集合,但您仍然需要对此进行处理。

    【讨论】:

      【解决方案2】:

      你必须为此写一个光标。请在下面找到相同的语法。

      语法:

      create or replace procedure select_procedure
      as
      CURSOR <cursor_name> IS <SELECT statement without semicolon>;
      BEGIN
        FOR record IN <cursor_name>
        LOOP
        Dbms_output.put_line(‘Record Fetched:‘||record.name);
        Dbms_output.put_line(‘Record Fetched:‘||record.surname);
        END LOOP;
      END;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-09-27
        • 2018-06-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多