Come restituire un CTE come refcursor da una stored procedure di Oracle?
-
16-10-2019 - |
Domanda
Ho cercato di modificare una stored procedure Oracle di utilizzare una CTE al posto di una semplice istruzione Select.
Il mio procedimento si presentava così:
Create or replace Myproc ( MyRefCursor IN OUT SYS_REFCURSOR)
as
begin
Open MyRefCursor for
Select * from ...something ...;
end;
/
Ho riscritto questa domanda:
Select * from ...something ...;
Dato che questo CTE:
with MyCTE As (
... ;
)
Select * from MyCTE;
L'apertura di un cursore in questo modo non funziona:
Open MyRefCursor for
with MyCTE As (
... ;
)
Select * from MyCTE;
Né questo:
with MyCTE As (
... ;
)
Open MyRefCursor for
Select * from MyCTE;
Soluzione
Dato che il CTE è parte della stessa istruzione SQL, non dovrebbe contenere un punto e virgola.
Quindi, non ci dovrebbero essere il punto e virgola sulla seconda riga del terzo blocco o la terza riga del quarto blocco. Il quinto blocco non ha un'istruzione SQL contigui.
Altri suggerimenti
Un completo esempio molto semplice utilizzando una stored procedura senza parametro di ingresso:
Alcuni dati demo:
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;
Ora una semplice stored procedure utilizzando un CTE banale:
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;
/
E infine una chiamata di prova per sqlplus o rospo
VAR R REFCURSOR
EXEC return_from_simple_cte (:R)
PRINT r
Sfondo a questa domanda:
Ho fatto la trasformazione del Select-dichiarazione per CTE in SQL-Server un Volevo aggiungere fila numeri al risultato. Ho semplicemente dimentico che aggiungere un alias per il *
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 nonreursive sembrano aiutare a migrare da SQL-Server a Oracle, ma ci sono alcune differenze di sintassi minore.