2009-06-17 6 views
2

Je tente d'écrire un proc stocké qui prend un nombre, n, et renvoie les n premiers résultats pour une requête donnée, en verrouillant exclusivement ces n lignes. Je suis un peu nouveau sur SQL et j'ai un peu de difficulté à faire correspondre correctement les types de données.problème de définition du curseur de référence faiblement défini

Mon spec paquet ressemble à ceci:

PACKAGE package IS 
    Type out_result_type is REF CURSOR; 
    PROCEDURE stored_proc 
    (in_n IN NUMBER DEFAULT 10, 
     out_list IN OUT out_result_type); 

Je Réglez ensuite le curseur dans le corps de la procédure, comme suit:

CURSOR OUT_RESULT_TYPE IS 
     SELECT a.id 
      FROM schema.table a 
      WHERE (some conditions) AND rownum <= in_n; 

Un peu plus tard, j'essaie ensuite d'extraire les résultats de le curseur dans la variable de sortie:

OPEN OUT_RESULT_TYPE; 
FETCH OUT_RESULT_TYPE INTO out_list; -- error on this line 
CLOSE OUT_RESULT_TYPE; 

Mais hélas, ce code ne compile pas; Oracle se plaint que out_list a déjà été défini avec un type de données en conflit. Une idée de comment je peux résoudre ce problème? Ça me rend fou!

Merci d'avance.

Répondre

1
CREATE OR REPLACE PACKAGE pkg_test 
AS 
     TYPE tt_cur IS REF CURSOR; 
     PROCEDURE prc_cur (retval OUT tt_cur); 
END; 

CREATE OR REPLACE PACKAGE BODY pkg_test 
AS 
     PROCEDURE prc_cur (retval OUT tt_cur) 
     AS 
     BEGIN 
       OPEN retval 
       FOR 
       SELECT * 
       FROM dual; 
     END; 
END; 

Si vous voulez verrouiller, utilisez:

CREATE OR REPLACE PACKAGE BODY pkg_test 
AS 
     PROCEDURE prc_cur (retval OUT tt_cur) 
     AS 
     BEGIN 
       OPEN retval 
       FOR 
       SELECT a.id 
       FROM schema.table a 
       WHERE (some conditions) 
         AND rownum <= in_n 
       ORDER BY 
         column 
       -- Never forget ORDER BY! 
       FOR UPDATE; 
     END; 
END; 
+0

Pourquoi ne pas utiliser sys_refcursor? – tuinstoel

+0

@tuinstoel: J'oublie toujours qu'il existe :) – Quassnoi

+0

Merci, c'était très utile –

0

Votre out_list doit être de mauvais type. Tenez compte (exécution du script sur 10.2.0.3):

CREATE TABLE t AS SELECT ROWNUM ID FROM all_objects WHERE ROWNUM <= 100; 

CREATE OR REPLACE PACKAGE cursor_pck AS 
    TYPE out_result_type is REF CURSOR; 
    PROCEDURE stored_proc (p_in IN NUMBER DEFAULT 10, 
          p_out_list IN OUT out_result_type); 
END cursor_pck; 
/

Si vous voulez sélectionner et verrouiller les lignes en même temps que vous utilisez la clause FOR UPDATE: Avec la configuration suivante

CREATE OR REPLACE PACKAGE BODY cursor_pck AS 
    PROCEDURE stored_proc (p_in IN NUMBER DEFAULT 10, 
          p_out_list IN OUT out_result_type) IS 
    BEGIN 
     OPEN p_out_list FOR SELECT a.id FROM t a WHERE ROWNUM <= p_in FOR UPDATE; 
    END stored_proc; 
END cursor_pck; 
/

, vous appellera la procédure comme ceci:

SQL> SET SERVEROUTPUT ON; 
SQL> DECLARE 
    2  l_cursor cursor_pck.out_result_type; 
    3  l_id t.id%TYPE; 
    4 BEGIN 
    5  cursor_pck.stored_proc(3, l_cursor); 
    6  LOOP 
    7  FETCH l_cursor INTO l_id; 
    8  EXIT WHEN l_cursor%NOTFOUND; 
    9  dbms_output.put_line(l_id); 
10  END LOOP; 
11 END; 
12/

1 
2 
3 

PL/SQL procedure successfully completed 
0

Cela ne va pas travailler la façon dont il est écrit, parce que

  1. out_list attend un curseur, pas le résultat du curseur.
  2. Le nom out_result_type est déjà utilisé pour un type , donc vous ne pouvez pas redéfinir être un curseur dans la même portée.
0

Oracle fournit un curseur de référence faible prédéfini: sys_refcursor. En utilisation, cela ressemblerait à:

CREATE OR REPLACE PACKAGE pkg_test 
AS 
    PROCEDURE prc_cur (p_retval OUT sys_refcursor, 
         p_lookup IN VARCHAR2); 
END pkg_test; 


CREATE OR REPLACE PACKAGE BODY pkg_test 
AS 
    PROCEDURE prc_cur(p_retval OUT sys_refcursor 
         p_lookup IN VARCHAR2) 
    IS 
    BEGIN 
     OPEN retval FOR SELECT a.value 
          FROM tblname a 
         WHERE a.id <= p_lookup; 
    END prc_cur; 
END pkg_test; 

Cela vous évite de devoir déclarer un type. Le sys_refcursor est un pointeur vers un jeu de résultats à partir d'un curseur ouvert. Si vous êtes familier avec Java, c'est le même concept que l'objet java.sql.ResultSet qui fournit un moyen d'obtenir les résultats d'une requête.

Questions connexes