Comment retourner un ensemble de résultats / curseur à partir D'un bloc Oracle PL/SQL anonymous qui exécute Dynamic SQL?
j'ai cette table:
ALLITEMS
---------------
ItemId | Areas
---------------
1 | EAST
2 | EAST
3 | SOUTH
4 | WEST
the DDL:
drop table allitems;
Create Table Allitems(ItemId Int,areas Varchar2(20));
Insert Into Allitems(Itemid,Areas) Values(1,'east');
Insert Into Allitems(ItemId,areas) Values(2,'east');
insert into allitems(ItemId,areas) values(3,'south');
insert into allitems(ItemId,areas) values(4,'east');
en MSSQL, pour obtenir un curseur d'un SQL dynamique je peux faire:
DECLARE @v_sqlStatement VARCHAR(2000);
SET @v_Sqlstatement = 'SELECT * FROM ALLITEMS';
EXEC (@v_sqlStatement); --returns a resultset/cursor, just like calling SELECT
dans Oracle, je dois utiliser un bloc PL/SQL:
SET AUTOPRINT ON;
DECLARE
V_Sqlstatement Varchar2(2000);
outputData SYS_REFCURSOR;
BEGIN
V_Sqlstatement := 'SELECT * FROM ALLITEMS';
OPEN outputData for v_Sqlstatement;
End;
--result is : anonymous block completed
mais tout ce que je reçois est"Bloc anonyme terminé".
Comment puis-je obtenir le retour du curseur?
(Je sais que si je ne AUTOPRINT, il va imprimer les informations dans le REFCURSOR (ce n'est pas l'impression dans le code ci-dessus, mais c'est un autre problème))
j'appellerai Ce SQL dynamique de code (ODBC,C++), et j'en ai besoin pour retourner un curseur.
Comment dois-je faire? Je suis perplexe.
4 réponses
vous pouvez écrire une fonction PL/SQL pour retourner ce curseur (ou vous pouvez mettre cette fonction dans un paquet si vous avez plus de code lié à cela):
CREATE OR REPLACE FUNCTION get_allitems
RETURN SYS_REFCURSOR
AS
my_cursor SYS_REFCURSOR;
BEGIN
OPEN my_cursor FOR SELECT * FROM allitems;
RETURN my_cursor;
END get_allitems;
renvoie le curseur.
assurez-vous de ne pas mettre votre SELECT
- chaîne de caractères entre guillemets dans PL/SQL lorsque cela est possible. Mettre dans des chaînes signifie qu'il ne peut pas être vérifié au moment de la compilation, et qu'il doit être analysé à chaque fois que vous l'utilisez.
si vous avez vraiment besoin d'utiliser dynamic SQL, vous pouvez mettre votre requête en guillemets simples:
OPEN my_cursor FOR 'SELECT * FROM allitems';
cette chaîne doit être analysée chaque fois que la fonction est appelée, ce qui sera généralement plus lent et cache des erreurs dans votre requête jusqu'à l'exécution.
assurez-vous d'utiliser des variables de liaison lorsque c'est possible pour éviter hard parses :
OPEN my_cursor FOR 'SELECT * FROM allitems WHERE id = :id' USING my_id;
en SQL*Plus vous pouvez également utiliser une REFCURSOR
variable:
SQL> VARIABLE x REFCURSOR
SQL> DECLARE
2 V_Sqlstatement Varchar2(2000);
3 BEGIN
4 V_Sqlstatement := 'SELECT * FROM DUAL';
5 OPEN :x for v_Sqlstatement;
6 End;
7 /
ProcÚdure PL/SQL terminÚe avec succÞs.
SQL> print x;
D
-
X
vous devriez pouvoir déclarer qu'un curseur est une variable de liaison (appelée Paramètres dans D'autres SGBD')
comme Vincent l'a écrit, Vous pouvez faire quelque chose comme ceci:
begin
open :yourCursor
for 'SELECT "'|| :someField ||'" from yourTable where x = :y'
using :someFilterValue;
end;
vous devez lier 3 vars à ce script. Une chaîne de caractères pour "someField", une valeur pour" someFilterValue "et un curseur pour" yourCursor " qui doit être déclaré comme var de sortie.
malheureusement, je n'ai aucune idée de comment vous feriez ça depuis C++. (Un pourrait dire heureusement pour moi, si. ;- ))
selon la bibliothèque d'accès que vous utilisez, cela peut être une douleur royale ou simple.