2010-03-24 12 views
7

Leider war der größte Teil meiner DB Erfahrung mit MSSQL, die dazu neigen, Ihre Hand viel mehr als Oracle zu halten. Was ich versuche zu tun ist in tSQL ziemlich trivial, pl/sql bereitet mir Kopfschmerzen.XML-Rückgabe von einer Oracle Stored Procedure

Ich habe folgendes Verfahren:

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; 

Wenn er ausgeführt wird, sollte es ein XML-Dokument mit der folgenden Struktur zurück:

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

Wenn ich führen Sie die Abfrage selbst, anstelle der USERID Parameter mit Eine Zeichenfolge und das Entfernen der "in" -Klausel, die Abfrage läuft gut und gibt die erwartete Struktur zurück.

Wenn jedoch die Prozedur versucht, die Abfrage auszuführen, die Ergebnisse der XMLELEMENT Funktion in den Parameter USERRECORD Ausgang vorbei, erhalte ich die folgende Ausnahme:

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 

ich diese nach unten nageln verwirrte versuchen und leider hat mein Google-Fu nicht geholfen. Ich habe viele Oracle SQL | XML-Beispiele gefunden, aber keine, die sich mit XML beschäftigen, kommen von einer Prozedur zurück.

Hinweis: Ich weiß, dass eine alternative Methode zum Abrufen von XML mit DBMS-Methoden existiert, aber es ist mein Verständnis, dass diese Funktionalität zugunsten von SQL | XML veraltet ist.

Antwort

10

Der Code beinhaltet folgende Leistungen:

u.USERID = USERID; 

Während Sie die nackten USERID beabsichtigen das Verfahren der Parameter zu sein, Oracle gibt tatsächlich bevorzugt die Benutzer-ID, die Spalte in der Tabelle ist. In der Tat es interpretiert sie als

u.USERID = u.USERID; 

Sie

u.USERID = USPX_GetUserbyID.USERID; 

verwenden können, aber es ist eine gute Praxis ein Präfix für PL/SQL-Variablen zu verwenden, um Verwirrung zu vermeiden. Ich tendiere nach v_ für Variablen und i_, o_, io_ für Eingangs-, Ausgangs- und Eingangs-/Ausgangsparameter.

+0

Vielen Dank! Das Ändern der Eingabeparameter funktioniert einwandfrei. –

+0

Netter Fang. Hab das nicht gesehen. – dacracot

2

Ihr Fehler hat nichts mit XML zu tun. Wenn Sie in PL/SQL eine Abfrage haben, die mehrere Zeilen zurückgibt, müssen Sie die Zeilen mit einem Cursor durchlaufen. Sie haben das INTO-Schlüsselwort verwendet, das nur eine einzige Zeile (oder in Ihrem Fall XML) verarbeiten kann.

+0

Das ist, was ich nicht verstehe. Es gibt nur einen einzigen Benutzerdatensatz, der mit der Abfrage übereinstimmt. Wenn ich die Abfrage selbst ausführe, wird nur eine einzige XML-Zeile in Oracle SQL Developer zurückgegeben (was, ich weiß, ist nicht unbedingt ein Hinweis darauf, was tatsächlich passiert ...) –

0

Ihre Abfrage gibt anscheinend mehr als eine Zeile zurück. Mit der Art, wie Sie Ihre Prozedur strukturiert haben, müssen Sie Ihre Abfrage so schreiben, dass sie eine einzelne Zeile zurückgibt, die das gesamte XML enthält. Dann sollten Sie den Fehler nicht erhalten.