Comment retourner un CTE comme refcursor d'une procédure stockée Oracle?
-
16-10-2019 - |
Question
J'ai essayé de modifier une procédure stockée Oracle pour utiliser un CTE au lieu d'une simple déclaration Select.
Ma procédure ressemblait à ceci:
Create or replace Myproc ( MyRefCursor IN OUT SYS_REFCURSOR)
as
begin
Open MyRefCursor for
Select * from ...something ...;
end;
/
Je réécrit cette requête:
Select * from ...something ...;
Comme ce CTE:
with MyCTE As (
... ;
)
Select * from MyCTE;
Ouverture d'un curseur de cette façon ne fonctionne pas:
Open MyRefCursor for
with MyCTE As (
... ;
)
Select * from MyCTE;
ne fait ceci:
with MyCTE As (
... ;
)
Open MyRefCursor for
Select * from MyCTE;
La solution
Étant donné que le CTE fait partie de la même instruction SQL, il ne doit pas contenir un point-virgule.
Donc, il ne devrait pas être sur la deuxième virgule ligne du troisième bloc ou la troisième ligne du quatrième bloc. Le cinquième bloc ne dispose pas d'une instruction SQL contiguë.
Autres conseils
Un exemple très basique complet en utilisant une procédure stockée sans paramètre d'entrée:
Certaines données de démonstration:
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;
Maintenant, une procédure stockée simple à l'aide d'un CTE trivial:
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;
/
Et enfin un appel test pour sqlplus ou TOAD
VAR R REFCURSOR
EXEC return_from_simple_cte (:R)
PRINT r
Contexte de cette question:
Je l'ai fait la transformation de la instruction_select à CTE sur SQL-server un que je voulais ajouter une ligne numéros au résultat. J'oublie simplement que ajouter un alias à la *
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;
/
nonreursive CTEs semblent aider à migrer de SQL Server pour Oracle, mais il y a quelques différences de syntaxe mineures.