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.

23
demandé sur Liao 2010-01-28 10:58:33

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;
36
répondu Peter Lang 2016-05-17 05:01:01

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
8
répondu Vincent Malgrat 2010-01-28 09:03:04

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.

1
répondu Robert Giesecke 2010-01-28 09:24:52

ce réglage doit être réglé:

SET SERVEROUTPUT ON 
-6
répondu jon 2014-08-02 19:00:14