Как вернуть CTE в качестве рефлекса из хранимой процедуры Oracle?

dba.stackexchange https://dba.stackexchange.com/questions/577

Вопрос

Я попытался изменить хранимую процедуру 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, но есть некоторые незначительные различия в синтаксисе.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с dba.stackexchange
scroll top