2014-09-01 33 views
0

我有一個問題,也許有人已經經歷了同樣的問題,可以提供幫助。我正在開發一個項目,我需要從分層數據創建分層XML文檔。 我有查詢,拉數據和我面臨的問題是查詢太長的查詢字符串參數接受由DBMS_XMLGEN.newcontextfromhierarchy(queryString varchar2)Oracle DBMS_XMLGEN.newcontext fromhierarchy( - > queryString)

我試過使用with子句,但那不是在從結果集中選擇看起來可以理解時識別。

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

呀,總是當代碼必須是在VARCHAR2上面有長度限制:-)

如果DBMS_XMLGEN.newcontextfromhierarchy已經接受一個CLOB的問題,解決方案還必須一直在構建CLOB在幾個文字塊,每個小於限制。但不幸的是,DBMS_XMLGEN.newcontext層次結構使用VARCHAR2。

經典的解決方案是將查詢寫入視圖,然後字符串可以簡單地「select * from myview where ...」。不幸的是,您需要一個「參數」視圖來放入START WITH條款。

這樣做的一種方法可能是使用此鏈接中#1所述的上下文:http://mahmoudoracle.blogspot.dk/2012/06/create-view-with-parameter.html#.VAVdNPmSwt0

創建上下文來保存參數(請參閱鏈接)。

定義視圖類似:

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

只要你DBMS_XMLGEN呼叫之前,設置參數:

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

然後查詢字符串也只是:

SELECT * FROM MY_VIEW 

這個方法可以處理查詢的時間長度,因爲它可以構建到視圖中(這是很多,我不知道現在有多少,但很多;-)

如果您的代碼的大部分是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

謝謝金,你指着我在右邊方向。選擇的最大部分是我用來從中進行選擇的查詢。我通過定義一個記錄對象並創建這些記錄的表格來解決這個問題,打開一個外部光標選擇到對象表中,然後將其轉換爲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');