2010-03-24 3 views
7

Malheureusement, la plupart de mon expérience DB a été avec MSSQL qui tend à tenir votre main beaucoup plus que Oracle. Ce que j'essaie de faire est assez trivial en tSQL, cependant, pl/sql me donne mal à la tête.Retour XML à partir d'une procédure stockée Oracle

J'ai la procédure suivante:

CREATE OR REPLACE PROCEDURE USPX_GetUserbyID (USERID USERS.USERID%TYPE, USERRECORD OUT XMLTYPE) AS 
BEGIN 

    SELECT XMLELEMENT("user" 
     , XMLATTRIBUTES(u.USERID AS "userid", u.companyid as "companyid", u.usertype as "usertype", u.status as "status", u.personid as "personid") 
     , XMLFOREST( p.FIRSTNAME AS "firstname" 
        , p.LASTNAME AS "lastname" 
        , p.EMAIL AS "email" 
        , p.PHONE AS "phone" 
        , p.PHONEEXTENSION AS "extension") 
     , XMLELEMENT("roles", 
       (SELECT XMLAGG(XMLELEMENT("role", r.ROLETYPE)) 
        FROM USER_ROLES r 
        WHERE r.USERID = USERID 
         AND r.ISACTIVE = 1 
       ) 
      ) 
     , XMLELEMENT("watches", 
       (SELECT XMLAGG(
        XMLELEMENT("watch", 
         XMLATTRIBUTES(w.WATCHID AS "id", w.TICKETID AS "ticket") 
        ) 
       ) 
       FROM USER_WATCHES w 
       WHERE w.USERID = USERID 
       AND w.ISACTIVE = 1 
       ) 
      ) 
     ) AS "RESULT" 
    INTO USERRECORD 
    FROM USERS u 
    LEFT JOIN PEOPLE p ON p.PERSONID = u.PERSONID 
    WHERE u.USERID = USERID; 
    END USPX_GetUserbyID; 

Lorsqu'il est exécuté, il doit retourner un document XML avec la structure suivante:

<user userid="" companyid="" usertype="" status="" personid=""> 
    <firstname /> 
    <lastname /> 
    <email /> 
    <phone /> 
    <extension /> 
    <roles> 
     <role /> 
    </roles> 
    <watches> 
     <watch id="" ticket="" /> 
    </watches> 
</user> 

Lorsque j'exécute la requête elle-même, en remplaçant le paramètre USERID avec une chaîne et en supprimant la clause "dans", la requête s'exécute correctement et renvoie la structure attendue.

Cependant, lorsque la procédure tente d'exécuter la requête, en passant les résultats de la fonction XMLELEMENT dans le paramètre de sortie userRecord, je reçois l'exception suivante:

Error report: ORA-01422: exact fetch returns more than requested number of rows ORA-06512: at "USPX_GETUSERBYID", line 4 ORA-06512: at line 3 
01422. 00000 - "exact fetch returns more than requested number of rows" 
*Cause: The number specified in exact fetch is less than the rows returned. 
*Action: Rewrite the query or change number of rows requested 

Je déconcerté en essayant de clouer ce bas , et malheureusement mon google-fu n'a pas aidé. J'ai trouvé beaucoup d'exemples Oracle SQL | XML, mais aucun qui traite des retours XML d'une procédure. Je sais qu'il existe une autre méthode de récupération de code XML à l'aide de méthodes SGBD, mais je crois comprendre que cette fonctionnalité est déconseillée en faveur de SQL | XML.

Répondre

10

Votre code comprend les éléments suivants:

u.USERID = USERID; 

Alors que vous avez l'intention de la USERID nue comme paramètre de la procédure, Oracle donne effectivement la préférence à la USERID qui est la colonne dans la table. En effet, il l'interprète comme

u.USERID = u.USERID; 

Vous pouvez utiliser

u.USERID = USPX_GetUserbyID.USERID; 

, mais il est bon d'utiliser un préfixe pour les variables PL/SQL pour éviter toute confusion. Je tends vers v_ pour les variables et i_, o_, io_ pour les paramètres d'entrée, de sortie et d'entrée/sortie.

+0

Merci! Changer le paramètre d'entrée fonctionne parfaitement. –

+0

Belle prise. Je n'ai pas vu ça. – dacracot

2

Votre erreur n'a rien à voir avec XML. En PL/SQL si vous avez une requête qui renvoie plusieurs lignes, vous devez parcourir les lignes avec un curseur. Vous avez utilisé le mot-clé INTO qui ne peut gérer qu'un seul résultat de ligne (ou XML dans votre cas).

+0

C'est ce que je ne comprends pas. Il n'y a qu'un seul enregistrement d'utilisateur qui correspond à la requête. Lorsque j'exécute la requête elle-même, seule une ligne XML est retournée dans Oracle SQL Developer (ce qui, je le sais, n'est pas nécessairement une indication de ce qui se passe réellement ...) –

0

Votre requête renvoie apparemment plus d'une ligne. Avec la façon dont vous avez structuré votre procédure, vous devez écrire votre requête de manière à ce qu'elle renvoie une seule ligne contenant tout le XML. Alors vous ne devriez pas recevoir l'erreur.

Questions connexes