2016-03-23 29 views
0

我試圖從Oracle SQL表中提取數據,當我將寫入文件寫入文件之外的文件如下例所示。但是,當我將寫入文件放入循環內時,在此代碼下面的代碼中,它會因ORA-31181錯誤而失敗。ORA-31181:PL/SQL DOM句柄訪問不再可用的節點

我想要做的更大的規模是通過寫入一個clob將它輸出到平面文件每次它繞過循環時獲得一個XML到文件的負載。

DECLARE -- this version of code works as the write to is outside loop 

l_file UTL_FILE.FILE_TYPE; 
l_clob CLOB; 
l_buffer VARCHAR2(32767); 
l_amount BINARY_INTEGER := 32767; 
l_pos  INTEGER := 1; 
l_extract_dir    CONSTANT dba_directories.directory_name%TYPE:= 'REPORTS_OUT_DIR'; -- \\data2\data\download\d7prdv1\prsrepreports 


l_xmltype XMLTYPE; 
l_domdoc dbms_xmldom.DOMDocument; 
l_root_node dbms_xmldom.DOMNode;  

l_message_node   dbms_xmldom.DOMNode; 

l_production_element dbms_xmldom.DOMElement; 
l_production_node  dbms_xmldom.DOMNode; 

    -- production XML elements, node, text 
l_prod_element     dbms_xmldom.DOMElement;  
l_prod_node   dbms_xmldom.DOMNode; 
l_prod_t_node   dbms_xmldom.DOMNode; 
l_prod_text   dbms_xmldom.DOMText; 
-- production XML elements, node, text, node 


CURSOR c_production 
IS SELECT prod.cre_surr_id   as cre_surr_id 
     , prod.production_type  as prodCategoryType 
    from productions prod    
    where prod.cre_surr_id in (1753959927,1753959929); 
BEGIN 
    UTL_FILE.FCLOSE_ALL; 
    l_file := UTL_FILE.fopen(l_extract_dir , 'Sample2.dat', 'w', 32767); 

-- Create an empty XML document 
l_domdoc := dbms_xmldom.newDomDocument; 

-- Create a root node 
l_root_node := dbms_xmldom.makeNode(l_domdoc); 

-- Create a message root node 
l_message_node := dbms_xmldom.appendChild(l_root_node 
             , dbms_xmldom.makeNode(dbms_xmldom.createElement(l_domdoc, 'message')) 
            );  

    FOR production_rec in c_production LOOP 

    l_production_element := dbms_xmldom.createElement(l_domdoc, 'production'); 
    l_production_node := dbms_xmldom.appendChild(l_message_node,dbms_xmldom.makeNode(l_production_element)); 

    -- prodCategoryType 
    l_prod_element := dbms_xmldom.createElement(l_domdoc, 'prodCategoryType'); 
    l_prod_node := dbms_xmldom.appendChild(l_production_node,dbms_xmldom.makeNode(l_prod_element)); 
    l_prod_text := dbms_xmldom.createTextNode(l_domdoc, production_rec.prodCategoryType); 
    l_prod_t_node := dbms_xmldom.appendChild(l_prod_node,dbms_xmldom.makeNode(l_prod_text)); 

    END LOOP; 

    l_xmltype := dbms_xmldom.getXmlType(l_domdoc); 
    dbms_xmldom.freeDocument(l_domdoc); 
    l_clob := l_xmltype.getClobVal; 
    DBMS_LOB.read (l_clob, l_amount, l_pos, l_buffer); 
    UTL_FILE.put(l_file, l_buffer); 
    l_pos := l_pos + l_amount; 
    UTL_FILE.fclose(l_file); 

END; 

下面的代碼創建一個錯誤消息,當我把寫入文件寫入循環。

錯誤消息如下。

在線路錯誤1 ORA-31181:PL/SQL DOM的句柄來訪問節點即不再可用 ORA-06512:在 「XDB.DBMS_XMLDOM」,線4735 ORA-06512:在 「XDB.DBMS_XMLDOM」行4762 ORA-06512:在管線52

DECLARE -- this version of code DOES not work and creates the ORA-31181 error 

l_file UTL_FILE.FILE_TYPE; 
l_clob CLOB; 
l_buffer VARCHAR2(32767); 
l_amount BINARY_INTEGER := 32767; 
l_pos  INTEGER := 1; 
l_extract_dir    CONSTANT dba_directories.directory_name%TYPE:= 'REPORTS_OUT_DIR'; -- \\data2\data\download\d7prdv1\prsrepreports 


l_xmltype XMLTYPE; 
l_domdoc dbms_xmldom.DOMDocument; 
l_root_node dbms_xmldom.DOMNode;  

l_message_node   dbms_xmldom.DOMNode; 

l_production_element dbms_xmldom.DOMElement; 
l_production_node  dbms_xmldom.DOMNode; 

    -- production XML elements, node, text 
l_prod_element     dbms_xmldom.DOMElement;  
l_prod_node   dbms_xmldom.DOMNode; 
l_prod_t_node   dbms_xmldom.DOMNode; 
l_prod_text   dbms_xmldom.DOMText; 
-- production XML elements, node, text, node 


CURSOR c_production 
IS SELECT prod.cre_surr_id   as cre_surr_id 
     , prod.production_type  as prodCategoryType 
    from productions prod    
    where prod.cre_surr_id in (1753959927,1753959929); 
BEGIN 
    UTL_FILE.FCLOSE_ALL; 
    l_file := UTL_FILE.fopen(l_extract_dir , 'Sample2.dat', 'w', 32767); 

    -- Create an empty XML document 
    l_domdoc := dbms_xmldom.newDomDocument; 

    -- Create a root node 
    l_root_node := dbms_xmldom.makeNode(l_domdoc); 

    -- Create a message root node 
    l_message_node := dbms_xmldom.appendChild(l_root_node 
             , dbms_xmldom.makeNode(dbms_xmldom.createElement(l_domdoc, 'message')) 
            );  



    FOR production_rec in c_production LOOP 

    l_production_element := dbms_xmldom.createElement(l_domdoc, 'production'); 
    l_production_node := dbms_xmldom.appendChild(l_message_node,dbms_xmldom.makeNode(l_production_element)); 

    -- prodCategoryType 
    l_prod_element := dbms_xmldom.createElement(l_domdoc, 'prodCategoryType'); 
    l_prod_node := dbms_xmldom.appendChild(l_production_node,dbms_xmldom.makeNode(l_prod_element)); 
    l_prod_text := dbms_xmldom.createTextNode(l_domdoc, production_rec.prodCategoryType); 
    l_prod_t_node := dbms_xmldom.appendChild(l_prod_node,dbms_xmldom.makeNode(l_prod_text)); 



    l_xmltype := dbms_xmldom.getXmlType(l_domdoc); 
    dbms_xmldom.freeDocument(l_domdoc); 
    l_clob := l_xmltype.getClobVal; 
    DBMS_LOB.read (l_clob, l_amount, l_pos, l_buffer); 
    UTL_FILE.put(l_file, l_buffer); 
    l_pos := l_pos + l_amount; 


    END LOOP; 

    UTL_FILE.fclose(l_file); 

END; 
+0

因爲該行的替換dbms_xmldom.freeDocument(l_domdoc);。 'dbms_xmldom.freeDocument(l_domdoc);' –

+0

那麼dbms_xmldom.freeDocument(l_domdoc)實際上是幹掉了什麼?它是XML文檔結構還是它擺脫了該結構中的數據? –

+0

釋放/銷燬整個xml結構。爲什麼你要寫入文件內循環? –

回答

0

最簡單的方法。

begin  
for rec in (SELECT xmlserialize(content xmlelement("production", 
       xmlelement("prodCategoryType",prod.production_type)) as varchar2(4000)) val from productions prod) loop 
dbms_output.put_line(rec.val) ; 
end loop;          
end;  

或者在你的代碼中聲明添加v_temp DBMS_XMLDOM.DOMNODE;temp:= DBMS_XMLDOM.REMOVECHILD(l_message_node,l_production_node);