2014-09-01 4 views
0

질문이 있는데 누군가가 동일한 문제를 해결하고 도움을 줄 수 있습니다. 계층 적 데이터에서 계층 적 XML 문서를 만들어야하는 프로젝트에서 작업하고 있습니다. I 데이터와 내가 직면하고있어 문제를 끌어 쿼리 쿼리 절과 함께를 사용 해봤 DBMS_XMLGEN.newcontextfromhierarchy (queryString이 VARCHAR2)에서 허용하는 쿼리 문자열 매개 변수Oracle DBMS_XMLGEN.newcontextfromhierarchy (-> queryString)

너무 긴하지만 그건 아니었다이다가 이해할 수있는 결과 세트에서 선택할 때 인식됩니다.

SELECT XMLRoot(XMLELEMENT 
      ("clients", 
      (SELECT DBMS_XMLGEN.getxmltype 
         (DBMS_XMLGEN.newcontextfromhierarchy 
          ('SELECT level, 
       XMLElement("client", 
         XMLElement("client_number", client_number), 
         XMLElement("parent_client_number", parent_client_number), 
         XMLElement("level", level), 
         XMLElement("client_level", client_level)) 
     FROM clients 
    START WITH parent_client_number = ''900002'' 
    CONNECT BY PRIOR client_number = parent_client_number 
    ORDER siblings BY parent_client_number')) 
       FROM DUAL), (XMLELEMENT())),VERSION '1.0') as XMLDATA 
    FROM DUAL; 

쿼리는 위의 것보다 훨씬 길지만 내가 실행중인 항목에 대한 아이디어를 줄 것입니다.

정확한 오류입니다.

ORA-01704: string literal too long 

누구나 전에이 문제에 직면 해 있었고이를 극복하기위한 아이디어가 있습니까?

감사합니다, 세르지오

답변

1

그래, 코드 DBMS_XMLGEN.newcontextfromhierarchy가 CLOB을 받아 들였다 경우

:-) 거기에 길이 제한으로 VARCHAR2에 있어야한다 항상 문제가이 솔루션은 것 CLOB를 여러 리터럴의 덩어리로 만들어서 제한보다 작게 만들었습니다. 그러나 불행하게도 DBMS_XMLGEN.newcontextfromhierarchy는 VARCHAR2를 사용합니다.

클래식 솔루션은 뷰로 쿼리를 작성한 다음 문자열을 "select * from myview where ..."로 지정할 수 있습니다. 불행히도 START 뷰에 "매개 변수"를 입력해야합니다. 절.

이 링크의 # 1에서 설명한대로 컨텍스트를 사용할 수 있습니다. http://mahmoudoracle.blogspot.dk/2012/06/create-view-with-parameter.html#.VAVdNPmSwt0.

매개 변수를 보관할 컨텍스트를 만듭니다 (링크 참조).

같은보기 무엇인가를 정의

CTX_PKG.SET_CONTEXT ('parm1', '900002'); 

그리고 쿼리 문자열 바로 다음과 같습니다 :

SELECT * FROM MY_VIEW 

그냥 DBMS_XMLGEN 호출하기 전에 매개 변수를 설정

select ... 
from ... 
start with SYS_CONTEXT ('MY_CTX', 'parm1') 
... 

이 방법은 뷰에 빌드 할 수있는만큼 오랫동안 쿼리를 처리 할 수 ​​있습니다 (많은 경우 k 지금은 얼마지만, 많이 ;-)

코드의 대부분이 XMLELEMENT ("클라이언트"... 인 경우) 부분, 대안 (아마도 간단) 솔루션과 같이 될 것이다 : 될 것

CREATE OR REPLACE FUNCTION MyXml (
    p_client_number  clients.client_number%type, 
    p_parent_client_number clients.parent_client_number%type, 
    ... 
) 
    RETURN xmltype 
IS 
    RETURN XMLELEMENT("client"...); 
END; 

그리고 DBMS_XMLGEN 통화에서 쿼리를 뭔가 같은 :

DBMS_XMLGEN.newcontextfromhierarchy(
    'SELECT level, 
MyXml(client_number, parent_client_number, ...) the_xml 
FROM clients 
START WITH parent_client_number = ''900002'' 
CONNECT BY PRIOR client_number = parent_client_number 
ORDER siblings BY parent_client_number') 

그냥 밖으로 모든 XML 생성 이동 함수는 코드를 충분히 작게 만들 수 있습니다. 다른 테이블 또는 조인이 있는지 여부 또는 함수에 대한 매개 변수의 수가 너무 많아서 달라질 수 있습니다.

이렇게하면 메서드가 선택 될 수 있습니다. 함수가 쿼리를 "작게"만드는 경우 더 간단한 방법입니다. 함수가 충분하지 않으면 매개 변수화 된 뷰가이를 처리 할 수 ​​있어야합니다.이 코드의 향후 관리자에게 어떤 일이 "불분명한지"알 수 있습니다.

0

감사합니다 Kim, 방향. 선택의 가장 큰 부분은 내가 선택하기 위해 사용했던 쿼리였습니다. 레코드 개체를 정의하고 그 레코드의 테이블을 생성하고, 개체의 테이블을 선택하는 외부 커서를 연 다음 DBMS_XMLGEN.newcontextfromhierarchy()의 SQL 쿼리 문자열 내의 테이블로이 문제를 캐스팅하여이 문제를 해결했습니다. 비슷한 문제가있는 사람이라면 도움이 될 것입니다.

이 함수는 패키지의 일부로 선언되었으며 패키지 사양에 포함되어야했습니다.

CREATE OR REPLACE TYPE client_record AS OBJECT(

     x1   varchar2(8 Byte), 
     x2   varchar2(3 Byte), 
     x3 varchar2(8 Byte), 
     x4   varchar2(22 Byte), 
     x5   CHAR(1) 
); 

CREATE OR REPLACE TYPE client_rec_tab IS TABLE OF client_record; 
/


FUNCTION get_merchant_hierarchy(x1 IN VARCHAR2, 
           x2 IN VARCHAR2 
) RETURN client_rec_tab 

IS some code to open cursor and bulk fetch into a client_rec_tab ... 

END get_merchant_hierarchy; 


     DBMS_XMLGEN.newcontextfromhierarchy 
          ('SELECT level, 
      XMLElement("client_details", 
         XMLElement("client_number", client_number), 
         XMLElement("client_level", client_level), 
         XMLElement("parent_client_number", parent_client_number), 
         XMLElement("trade_name", trade_name), 
         XMLElement("billing_level", billing_level)) 
     FROM table(package.get_merchant_hierarchy(:1,:2)) 
    START WITH client_number = (select client_number from table(package.get_merchant_hierarchy(:1,:2)) where client_level = ''002'') 
    CONNECT BY PRIOR client_number = parent_client_number 
    ORDER siblings BY parent_client_number');