Как вернуть CTE в качестве рефлекса из хранимой процедуры Oracle?
-
16-10-2019 - |
Вопрос
Я попытался изменить хранимую процедуру Oracle для использования CTE вместо простого оператора SELECT.
Моя процедура выглядела так:
Create or replace Myproc ( MyRefCursor IN OUT SYS_REFCURSOR)
as
begin
Open MyRefCursor for
Select * from ...something ...;
end;
/
Я переписал этот запрос:
Select * from ...something ...;
Как этот CTE:
with MyCTE As (
... ;
)
Select * from MyCTE;
Открытие курсора таким образом не работает:
Open MyRefCursor for
with MyCTE As (
... ;
)
Select * from MyCTE;
Также не так:
with MyCTE As (
... ;
)
Open MyRefCursor for
Select * from MyCTE;
Решение
Поскольку CTE является частью того же оператора SQL, он не должен содержать полуколон.
Таким образом, на второй строке третьего блока или третьей строки четвертого блока не должно быть полуколона. Пятый блок не имеет смежного оператора SQL.
Другие советы
Полный очень основной пример с использованием хранимой процедуры без входного параметра:
Некоторые демонстрационные данные:
CREATE TABLE DEMO(
id NUMBER(10),
type NUMBER(10),
code varchar2(20)
);
Insert INTO DEMO values (1, 0, 'a');
Insert INTO DEMO values (2, 0, 'b');
Insert INTO DEMO values (3, 0, 'c');
Insert INTO DEMO values (4, 1, 'd');
Insert INTO DEMO values (5, 1, 'e');
Insert INTO DEMO values (6, 1, 'f');
SELECT * from DEMO;
Теперь простая сохраненная процедура с использованием тривиального CTE:
create or replace procedure return_from_simple_cte
(
MyRefCursor IN OUT SYS_REFCURSOR
)
AS
BEGIN
Open MyRefCursor for
WITH My_CTE AS(
SELECT * FROM DEMO WHERE Type = 1
)
Select * FROM My_CTE;
END;
/
И, наконец, тестовый звонок для SQLPLUS или TOAD
VAR R REFCURSOR
EXEC return_from_simple_cte (:R)
PRINT r
Фон для этого вопроса:
Я сделал преобразование Select-Statement в CTE на SQL-Server, и я хотел добавить в результат числа строк. Я просто забыл, что добавить псевдоним к *
create or replace PROCEDURE TEChange
(
MyRefCursor IN OUT SYS_REFCURSOR
,p_TERefnr NUMBER
)
AS
BEGIN
Open MyRefCursor for
WITH TE_CTE AS (
SELECT TeRefnr
FROM vSYSTE
WHERE TERefnr <> p_TERefnr
)
Select
ROW_NUMBER() over(order by TERefnr) Nr,
t.*
from TE_CTE t;
END;
/
Несурсивные CTE, похоже, помогают мигрировать с SQL-сервер в Oracle, но есть некоторые незначительные различия в синтаксисе.