Как получить блок PL/SQL для вывода результатов оператора SELECT
так же, как если бы я сделал простой SELECT
?
Например, как сделать SELECT
как:
SELECT foo, bar FROM foobar;
Подсказка:
BEGIN
SELECT foo, bar FROM foobar;
END;
не работает.
Как получить блок PL/SQL для вывода результатов оператора SELECT
так же, как если бы я сделал простой SELECT
?
Например, как сделать SELECT
как:
SELECT foo, bar FROM foobar;
Подсказка:
BEGIN
SELECT foo, bar FROM foobar;
END;
не работает.
Это зависит от того, для чего вам нужен результат.
Если вы уверены, что будет только одна строка, используйте неявный курсор:
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;
Если вы хотите выбрать более одной строки, вы можете использовать явный курсор:
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;
или используйте другой тип курсора:
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;
Вы можете сделать это в Oracle 12.1 или выше:
declare
rc sys_refcursor;
begin
open rc for select * from dual;
dbms_sql.return_result(rc);
end;
У меня нет DBVisualizer для тестирования, но это, вероятно, должно быть вашей отправной точкой.
Дополнительные сведения см. в разделе "Неявные наборы результатов" в Руководстве по новым функциям Oracle 12.1, Oracle Base и т.д.
Для более ранних версий, в зависимости от инструмента, вы можете использовать переменные привязки курсора 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.
Создайте функцию в пакете и верните 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;
От анонимного блока? Я бы хотел больше узнать о ситуации, когда вы считаете, что это необходимо, потому что с предложениями факторинга подзапросов и встроенными представлениями довольно редко приходится обращаться к PL/SQL для чего-либо другого, кроме самых сложных ситуаций.
Если вы можете использовать именованную процедуру, используйте конвейерные функции. Вот пример, извлеченный из документации:
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));
Классический 'Hello World!' Блок содержит исполняемый раздел, который вызывает процедуру DBMS_OUTPUT.PUT_LINE
для отображения текста на экране:
BEGIN
DBMS_OUTPUT.put_line ('Hello World!');
END;
Вы можете оформить заказ здесь:http://www.oracle.com/technetwork/issue-archive/2011/11-mar/o21plsql-242570.html
если вы хотите увидеть выбор вывода запроса в pl/sql, вам нужно использовать явный курсор. Это будет содержать активный набор данных и выборка каждой строки за раз, пока она будет отображать всю запись из активного набора данных, если она извлекает данные из набора данных, итерации в цикле. Эти данные не будут генерироваться в табличном формате, этот результат будет в текстовом формате. Надеюсь, это будет полезно. Для любого другого запроса вы можете спросить....
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;
Для версий ниже 12c простой ответ НЕТ, по крайней мере, не так, как это делается, это SQL Server.
Вы можете распечатать результаты, вы можете вставлять результаты в таблицы, вы можете возвращать результаты в виде курсоров из функции/процедуры или возвращать набор строк из функции -
но вы не можете выполнять инструкцию SELECT, не делая ничего с результатами.
begin
select 1+1
select 2+2
select 3+3
end
/* 3 возвращенных набора результатов */
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
Вам нужно использовать собственный динамический SQL. Кроме того, для запуска команды SQL не требуется BEGIN-END:
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
использовать немедленную инструкцию
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;
Даже если вопрос старый, но я поделюсь решением, которое идеально ответит на вопрос:
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;
Курсоры используются, когда ваш запрос на выборку возвращает несколько строк. Таким образом, вместо использования курсора, если вам нужны агрегаты или отдельные строки, вы можете использовать процедуру/функцию без курсора, например,
Create Procedure sample(id
varchar2(20))as
Select count(*) into x from table
where
Userid=id;
End ;
А потом просто вызовите процедуру
Begin
sample(20);
End
Это фактическое использование процедуры/функции, в основном для упаковки и хранения запросов, которые являются сложными или требуют многократных манипуляций с той же логикой, но разными данными.