是否可以从PL / SQL块输出SELECT语句?

时间:2021-11-26 14:07:31

How can I get a PL/SQL block to output the results of a SELECT statement the same way as if I had done a plain SELECT?

如何获得PL / SQL块以输出SELECT语句的结果,就像我做了一个普通的SELECT一样?

For example how to do a SELECT like:

例如,如何做SELECT:

SELECT foo, bar FROM foobar;

Hint :

BEGIN
SELECT foo, bar FROM foobar;
END;

doesn't work.

10 个解决方案

#1


32  

It depends on what you need the result for.

这取决于你需要的结果。

If you are sure that there's going to be only 1 row, use implicit cursor:

如果您确定只有一行,请使用隐式游标:

DECLARE
   v_foo foobar.foo%TYPE;
   v_bar foobar.bar%TYPE;
BEGIN
   SELECT foo,bar FROM foobar INTO v_foo, v_bar;
   -- Print the foo and bar values
   dbms_output.put_line('foo=' || v_foo || ', bar=' || v_bar);
EXCEPTION
   WHEN NO_DATA_FOUND THEN
     -- No rows selected, insert your exception handler here
   WHEN TOO_MANY_ROWS THEN
     -- More than 1 row seleced, insert your exception handler here
END;

If you want to select more than 1 row, you can use either an explicit cursor:

如果要选择多于一行,可以使用显式游标:

DECLARE
   CURSOR cur_foobar IS
     SELECT foo, bar FROM foobar;

   v_foo foobar.foo%TYPE;
   v_bar foobar.bar%TYPE;
BEGIN
   -- Open the cursor and loop through the records
   OPEN cur_foobar;
   LOOP
      FETCH cur_foobar INTO v_foo, v_bar;
      EXIT WHEN cur_foobar%NOTFOUND;
      -- Print the foo and bar values
      dbms_output.put_line('foo=' || v_foo || ', bar=' || v_bar);
   END LOOP;
   CLOSE cur_foobar;
END;

or use another type of cursor:

或使用其他类型的游标:

BEGIN
   -- Open the cursor and loop through the records
   FOR v_rec IN (SELECT foo, bar FROM foobar) LOOP       
   -- Print the foo and bar values
   dbms_output.put_line('foo=' || v_rec.foo || ', bar=' || v_rec.bar);
   END LOOP;
END;

#2


24  

You can do this in Oracle 12.1 or above:

您可以在Oracle 12.1或更高版本中执行此操作:

declare
    rc sys_refcursor;
begin
    open rc for select * from dual;
    dbms_sql.return_result(rc);
end;

I don't have a 12.x database or DBVisualizer to test with, but that should probably be your starting point.

我没有12.x数据库或DBVisualizer来测试,但这应该是你的起点。

For more details, see Implicit Result Sets in the Oracle 12.1 New Features Guide, Tom Kyte's Blog, Oracle Base etc.

有关更多详细信息,请参阅Oracle 12.1新增功能指南,Tom Kyte博客,Oracle Base等中的隐式结果集。

For earlier versions, depending on the tool you might be able to use ref cursor bind variables like this example from SQL*Plus:

对于早期版本,根据工具,您可以使用ref游标绑定变量,如SQL * Plus中的此示例:

set autoprint on

var rc refcursor

begin
    open :rc for select count(*) from dual;
end;
/

PL/SQL procedure successfully completed.


  COUNT(*)
----------
         1

1 row selected.

#3


7  

Create a function in a package and return a SYS_REFCURSOR:

在包中创建一个函数并返回一个SYS_REFCURSOR:

FUNCTION Function1 return SYS_REFCURSOR IS 
       l_cursor SYS_REFCURSOR;
       BEGIN
          open l_cursor for SELECT foo,bar FROM foobar; 
          return l_cursor; 
END Function1;

#4


6  

From an anonymous block? I'd like to now more about the situation where you think that to be required, because with subquery factoring clauses and inline views it's pretty rare that you need to resort to PL/SQL for anything other than the most complex situations.

从一个匿名的块?我现在想更多地了解您认为需要的情况,因为使用子查询因子子句和内联视图,除了最复杂的情​​况之外,您需要求助于PL / SQL。

If you can use a named procedure then use pipelined functions. Here's an example pulled from the documentation:

如果可以使用命名过程,则使用流水线函数。以下是从文档中提取的示例:

CREATE PACKAGE pkg1 AS
  TYPE numset_t IS TABLE OF NUMBER;
  FUNCTION f1(x NUMBER) RETURN numset_t PIPELINED;
END pkg1;
/

CREATE PACKAGE BODY pkg1 AS
-- FUNCTION f1 returns a collection of elements (1,2,3,... x)
FUNCTION f1(x NUMBER) RETURN numset_t PIPELINED IS
  BEGIN
    FOR i IN 1..x LOOP
      PIPE ROW(i);
    END LOOP;
    RETURN;
  END;
END pkg1;
/

-- pipelined function is used in FROM clause of SELECT statement
SELECT * FROM TABLE(pkg1.f1(5));

#5


4  

The classic “Hello World!” block contains an executable section that calls the DBMS_OUTPUT.PUT_LINE procedure to display text on the screen:

经典的“Hello World!”块包含一个可执行部分,它调用DBMS_OUTPUT.PUT_LINE过程以在屏幕上显示文本:

BEGIN
  DBMS_OUTPUT.put_line ('Hello World!');
END;

You can checkout it here: http://www.oracle.com/technetwork/issue-archive/2011/11-mar/o21plsql-242570.html

你可以在这里查看:http://www.oracle.com/technetwork/issue-archive/2011/11-mar/o21plsql-242570.html

#6


4  

if you want see select query output in pl/sql you need to use a explicit cursor. Which will hold active data set and by fetching each row at a time it will show all the record from active data set as long as it fetches record from data set by iterating in loop. This data will not be generated in tabular format this result will be in plain text format. Hope this will be helpful. For any other query you may ask....

如果你想在pl / sql中看到select查询输出,你需要使用显式游标。其中将保存活动数据集,并且通过一次获取每一行它将显示来自活动数据集的所有记录,只要它通过迭代循环从数据集中获取记录。此数据不会以表格格式生成,此结果将采用纯文本格式。希望这会有所帮助。对于任何其他查询,您可能会问....

set serveroutput on;
declare
cursor c1 is
   select foo, bar from foobar;
begin
  for i in c1 loop
    dbms_output.put_line(i.foo || ' ' || i.bar);
  end loop;
end;

#7


3  

For versions below 12c, the plain answer is NO, at least not in the manner it is being done is SQL Server.
You can print the results, you can insert the results into tables, you can return the results as cursors from within function/procedure or return a row set from function -
but you cannot execute SELECT statement, without doing something with the results.

对于低于12c的版本,简单的答案是否定的,至少不是以SQL Server的方式完成的。您可以打印结果,可以将结果插入表中,您可以将结果作为游标从函数/过程中返回或从函数返回行集 - 但是您无法执行SELECT语句,而无需对结果执行某些操作。


SQL Server

begin
    select 1+1
    select 2+2
    select 3+3
end

/* 3 result sets returned */

/ * 3结果集返回* /


Oracle

SQL> begin
  2  select 1+1 from dual;
  3  end;
  4  /
select * from dual;
*
ERROR at line 2:
ORA-06550: line 2, column 1:
PLS-00428: an INTO clause is expected in this SELECT statement

#8


2  

You need to use Native dynamic SQL. Also, you do not need BEGIN-END to run SQL command:

您需要使用Native动态SQL。此外,您不需要BEGIN-END来运行SQL命令:

declare
  l_tabname VARCHAR2(100) := 'dual';
  l_val1    VARCHAR2(100):= '''foo''';
  l_val2    VARCHAR2(100):= '''bar''';
  l_sql     VARCHAR2(1000);  
begin
  l_sql:= 'SELECT '||l_val1||','||l_val2||' FROM '||l_tabname;
  execute immediate l_sql;
  dbms_output.put_line(l_sql);
end;
/

Output:
 SELECT 'foo','bar' FROM dual

#9


1  

use execute immediate statement

使用execute immediate语句

like:

declare
 var1    integer;
var2 varchar2(200)
begin
 execute immediate 'select emp_id,emp_name from emp'
   into var1,var2;
 dbms_output.put_line(var1 || var2);
end;

#10


0  

Even if the question is old but i will share the solution that answers perfectly the question :

即使问题很老,但我会分享完全回答问题的解决方案:

SET SERVEROUTPUT ON;

DECLARE
    RC SYS_REFCURSOR;
    Result1 varchar2(25);
    Result2 varchar2(25);
BEGIN
    OPEN RC FOR SELECT foo, bar into Result1, Result2 FROM foobar;
    DBMS_SQL.RETURN_RESULT(RC);
END;

#1


32  

It depends on what you need the result for.

这取决于你需要的结果。

If you are sure that there's going to be only 1 row, use implicit cursor:

如果您确定只有一行,请使用隐式游标:

DECLARE
   v_foo foobar.foo%TYPE;
   v_bar foobar.bar%TYPE;
BEGIN
   SELECT foo,bar FROM foobar INTO v_foo, v_bar;
   -- Print the foo and bar values
   dbms_output.put_line('foo=' || v_foo || ', bar=' || v_bar);
EXCEPTION
   WHEN NO_DATA_FOUND THEN
     -- No rows selected, insert your exception handler here
   WHEN TOO_MANY_ROWS THEN
     -- More than 1 row seleced, insert your exception handler here
END;

If you want to select more than 1 row, you can use either an explicit cursor:

如果要选择多于一行,可以使用显式游标:

DECLARE
   CURSOR cur_foobar IS
     SELECT foo, bar FROM foobar;

   v_foo foobar.foo%TYPE;
   v_bar foobar.bar%TYPE;
BEGIN
   -- Open the cursor and loop through the records
   OPEN cur_foobar;
   LOOP
      FETCH cur_foobar INTO v_foo, v_bar;
      EXIT WHEN cur_foobar%NOTFOUND;
      -- Print the foo and bar values
      dbms_output.put_line('foo=' || v_foo || ', bar=' || v_bar);
   END LOOP;
   CLOSE cur_foobar;
END;

or use another type of cursor:

或使用其他类型的游标:

BEGIN
   -- Open the cursor and loop through the records
   FOR v_rec IN (SELECT foo, bar FROM foobar) LOOP       
   -- Print the foo and bar values
   dbms_output.put_line('foo=' || v_rec.foo || ', bar=' || v_rec.bar);
   END LOOP;
END;

#2


24  

You can do this in Oracle 12.1 or above:

您可以在Oracle 12.1或更高版本中执行此操作:

declare
    rc sys_refcursor;
begin
    open rc for select * from dual;
    dbms_sql.return_result(rc);
end;

I don't have a 12.x database or DBVisualizer to test with, but that should probably be your starting point.

我没有12.x数据库或DBVisualizer来测试,但这应该是你的起点。

For more details, see Implicit Result Sets in the Oracle 12.1 New Features Guide, Tom Kyte's Blog, Oracle Base etc.

有关更多详细信息,请参阅Oracle 12.1新增功能指南,Tom Kyte博客,Oracle Base等中的隐式结果集。

For earlier versions, depending on the tool you might be able to use ref cursor bind variables like this example from SQL*Plus:

对于早期版本,根据工具,您可以使用ref游标绑定变量,如SQL * Plus中的此示例:

set autoprint on

var rc refcursor

begin
    open :rc for select count(*) from dual;
end;
/

PL/SQL procedure successfully completed.


  COUNT(*)
----------
         1

1 row selected.

#3


7  

Create a function in a package and return a SYS_REFCURSOR:

在包中创建一个函数并返回一个SYS_REFCURSOR:

FUNCTION Function1 return SYS_REFCURSOR IS 
       l_cursor SYS_REFCURSOR;
       BEGIN
          open l_cursor for SELECT foo,bar FROM foobar; 
          return l_cursor; 
END Function1;

#4


6  

From an anonymous block? I'd like to now more about the situation where you think that to be required, because with subquery factoring clauses and inline views it's pretty rare that you need to resort to PL/SQL for anything other than the most complex situations.

从一个匿名的块?我现在想更多地了解您认为需要的情况,因为使用子查询因子子句和内联视图,除了最复杂的情​​况之外,您需要求助于PL / SQL。

If you can use a named procedure then use pipelined functions. Here's an example pulled from the documentation:

如果可以使用命名过程,则使用流水线函数。以下是从文档中提取的示例:

CREATE PACKAGE pkg1 AS
  TYPE numset_t IS TABLE OF NUMBER;
  FUNCTION f1(x NUMBER) RETURN numset_t PIPELINED;
END pkg1;
/

CREATE PACKAGE BODY pkg1 AS
-- FUNCTION f1 returns a collection of elements (1,2,3,... x)
FUNCTION f1(x NUMBER) RETURN numset_t PIPELINED IS
  BEGIN
    FOR i IN 1..x LOOP
      PIPE ROW(i);
    END LOOP;
    RETURN;
  END;
END pkg1;
/

-- pipelined function is used in FROM clause of SELECT statement
SELECT * FROM TABLE(pkg1.f1(5));

#5


4  

The classic “Hello World!” block contains an executable section that calls the DBMS_OUTPUT.PUT_LINE procedure to display text on the screen:

经典的“Hello World!”块包含一个可执行部分,它调用DBMS_OUTPUT.PUT_LINE过程以在屏幕上显示文本:

BEGIN
  DBMS_OUTPUT.put_line ('Hello World!');
END;

You can checkout it here: http://www.oracle.com/technetwork/issue-archive/2011/11-mar/o21plsql-242570.html

你可以在这里查看:http://www.oracle.com/technetwork/issue-archive/2011/11-mar/o21plsql-242570.html

#6


4  

if you want see select query output in pl/sql you need to use a explicit cursor. Which will hold active data set and by fetching each row at a time it will show all the record from active data set as long as it fetches record from data set by iterating in loop. This data will not be generated in tabular format this result will be in plain text format. Hope this will be helpful. For any other query you may ask....

如果你想在pl / sql中看到select查询输出,你需要使用显式游标。其中将保存活动数据集,并且通过一次获取每一行它将显示来自活动数据集的所有记录,只要它通过迭代循环从数据集中获取记录。此数据不会以表格格式生成,此结果将采用纯文本格式。希望这会有所帮助。对于任何其他查询,您可能会问....

set serveroutput on;
declare
cursor c1 is
   select foo, bar from foobar;
begin
  for i in c1 loop
    dbms_output.put_line(i.foo || ' ' || i.bar);
  end loop;
end;

#7


3  

For versions below 12c, the plain answer is NO, at least not in the manner it is being done is SQL Server.
You can print the results, you can insert the results into tables, you can return the results as cursors from within function/procedure or return a row set from function -
but you cannot execute SELECT statement, without doing something with the results.

对于低于12c的版本,简单的答案是否定的,至少不是以SQL Server的方式完成的。您可以打印结果,可以将结果插入表中,您可以将结果作为游标从函数/过程中返回或从函数返回行集 - 但是您无法执行SELECT语句,而无需对结果执行某些操作。


SQL Server

begin
    select 1+1
    select 2+2
    select 3+3
end

/* 3 result sets returned */

/ * 3结果集返回* /


Oracle

SQL> begin
  2  select 1+1 from dual;
  3  end;
  4  /
select * from dual;
*
ERROR at line 2:
ORA-06550: line 2, column 1:
PLS-00428: an INTO clause is expected in this SELECT statement

#8


2  

You need to use Native dynamic SQL. Also, you do not need BEGIN-END to run SQL command:

您需要使用Native动态SQL。此外,您不需要BEGIN-END来运行SQL命令:

declare
  l_tabname VARCHAR2(100) := 'dual';
  l_val1    VARCHAR2(100):= '''foo''';
  l_val2    VARCHAR2(100):= '''bar''';
  l_sql     VARCHAR2(1000);  
begin
  l_sql:= 'SELECT '||l_val1||','||l_val2||' FROM '||l_tabname;
  execute immediate l_sql;
  dbms_output.put_line(l_sql);
end;
/

Output:
 SELECT 'foo','bar' FROM dual

#9


1  

use execute immediate statement

使用execute immediate语句

like:

declare
 var1    integer;
var2 varchar2(200)
begin
 execute immediate 'select emp_id,emp_name from emp'
   into var1,var2;
 dbms_output.put_line(var1 || var2);
end;

#10


0  

Even if the question is old but i will share the solution that answers perfectly the question :

即使问题很老,但我会分享完全回答问题的解决方案:

SET SERVEROUTPUT ON;

DECLARE
    RC SYS_REFCURSOR;
    Result1 varchar2(25);
    Result2 varchar2(25);
BEGIN
    OPEN RC FOR SELECT foo, bar into Result1, Result2 FROM foobar;
    DBMS_SQL.RETURN_RESULT(RC);
END;