2012-05-23 9 views
59

मैं डेटाबेस में CLOB एस डालने की कोशिश कर रहा हूं (related question देखें)। मैं समझ नहीं पा रहा हूं कि क्या गलत है। मेरे पास लगभग 85 क्लॉब्स की एक सूची है जो मैं एक टेबल में डालना चाहता हूं। यहां तक ​​कि केवल पहली क्लॉब डालने पर मुझे ORA-00911: invalid character मिलता है। मैं इसे निष्पादित करने से पहले PreparedStatement से बयान प्राप्त करने का तरीका नहीं समझ सकता, इसलिए मैं 100% निश्चित नहीं हो सकता कि यह सही है, लेकिन अगर मुझे यह सही लगता है, तो यह बिल्कुल इस तरह दिखना चाहिए:मेरा अमान्य चरित्र कहां है (ORA-00911)

insert all 
    into domo_queries values ('select 
substr(to_char(max_data),1,4) as year, 
substr(to_char(max_data),5,6) as month, 
max_data 
from dss_fin_user.acq_dashboard_src_load_success 
where source = ''CHQ PeopleSoft FS''') 
select * from dual; 

आखिरकार, यह insert all कथन में into है, इसलिए मैं नियमित रूप से नियमित insert कथन नहीं करता हूं। मुझे वहां एक अमान्य चरित्र नहीं दिख रहा है, है ना? (ओह, और से ऊपर वाला कोड ठीक है जब मैं इसे अपने एसक्यूएल डेवलपर टूल में चलाता हूं।) और यदि मैं PreparedStatement में सेमी-कोलन को हटा देता हूं, तो यह ORA-00933: SQL command not properly ended त्रुटि फेंकता है।

किसी भी मामले में, क्वेरी निष्पादित करने के लिए मेरा कोड यहां है (और ऊपर दिए गए उदाहरण के लिए चर के मान)।

public ResultSet executeQuery(String connection, String query, QueryParameter... params) throws DataException, SQLException { 
    // query at this point = "insert all 
          //into domo_queries values (?) 
          //select * from dual;" 
    Connection conn = ConnectionPool.getInstance().get(connection); 
    PreparedStatement pstmt = conn.prepareStatement(query); 
    for (int i = 1; i <= params.length; i++) { 
    QueryParameter param = params[i - 1]; 
    switch (param.getType()) { //The type in the example is QueryParameter.CLOB 
     case QueryParameter.CLOB: 
     Clob clob = CLOB.createTemporary(conn, false, oracle.sql.CLOB.DURATION_SESSION); 
     clob.setString(i, "'" + param.getValue() + "'"); 
     //the value of param.getValue() at this point is: 
     /* 
     * select 
     * substr(to_char(max_data),1,4) as year, 
     * substr(to_char(max_data),5,6) as month, 
     * max_data 
     * from dss_fin_user.acq_dashboard_src_load_success 
     * where source = ''CHQ PeopleSoft FS'' 
     */ 
     pstmt.setClob(i, clob); 
     break; 
     case QueryParameter.STRING: 
     pstmt.setString(i, "'" + param.getValue() + "'"); 
     break; 
    } 
    } 
    ResultSet rs = pstmt.executeQuery(); //Obviously, this is where the error is thrown 
    conn.commit(); 
    ConnectionPool.getInstance().release(conn); 
    return rs; 
} 

क्या कुछ भी है जो मुझे अभी बड़ा समय याद आ रहा है?

+0

क्या आप इसे तैयार करने के लिए तैयार स्ट्रेटमेंट को एक स्ट्रिंग के रूप में देख सकते हैं? –

+0

मैंने उस पोस्ट में उल्लेख किया है। मैं यह नहीं समझ सकता कि यह कैसे करें। इंटरनेट पर जो कुछ भी मैं देखता हूं वह यह है कि यह किसी कारण से बहुत जटिल है ... – kentcdodds

+0

कुछ जेडीबीसी ड्राइवर आपको स्ट्रिंग() को तैयार किए गए स्टेटमेंट से क्वेरी दिखाने की अनुमति देते हैं और कुछ नहीं करते हैं। ओरेकल के बारे में निश्चित नहीं है। –

उत्तर

146

यदि आप हमें दिखाए गए स्ट्रिंग अक्षर का उपयोग करते हैं, तो समस्या अंत में ; वर्ण है। आप जेडीबीसी कॉल में क्वेरी स्ट्रिंग में शामिल नहीं हो सकते हैं।

जैसे ही आप केवल एक पंक्ति डाल रहे हैं, एक नियमित INSERT एकाधिक पंक्तियों को डालने पर भी ठीक होना चाहिए। एक बैच किए गए कथन का उपयोग करना संभवतः अधिक कुशल है। INSERT ALL के लिए कोई ज़रूरत नहीं है। इसके अतिरिक्त आपको अस्थायी क्लोब और वह सब कुछ नहीं चाहिए। आप कुछ इस तरह करने के लिए अपने विधि सरल बना सकते हैं (यह मानते हुए मैं मानकों का अधिकार मिल गया):

String query1 = "select substr(to_char(max_data),1,4) as year, " + 
    "substr(to_char(max_data),5,6) as month, max_data " + 
    "from dss_fin_user.acq_dashboard_src_load_success " + 
    "where source = 'CHQ PeopleSoft FS'"; 

String query2 = "....."; 

String sql = "insert into domo_queries (clob_column) values (?)"; 
PreparedStatement pstmt = con.prepareStatement(sql); 
StringReader reader = new StringReader(query1); 
pstmt.setCharacterStream(1, reader, query1.length()); 
pstmt.addBatch(); 

reader = new StringReader(query2); 
pstmt.setCharacterStream(1, reader, query2.length()); 
pstmt.addBatch(); 

pstmt.executeBatch(); 
con.commit(); 
+0

हाँ, किसी और ने इसका भी उल्लेख किया। जब मैं इसे बाहर निकालता हूं तो मुझे 'ओआरए -00 9 33: एसक्यूएल कमांड ठीक तरह से समाप्त नहीं होता है' त्रुटि ... – kentcdodds

+0

@kentcdodds: आप पहले स्थान पर 'सभी डालने' का उपयोग क्यों कर रहे हैं? एक सामान्य डालने ठीक होना चाहिए। –

+0

मेरे मूल प्रश्न में मैं उल्लेख करता हूं कि आप जो देखते हैं वह केवल यह सुनिश्चित करने के लिए एक परीक्षण है कि केवल एक ही प्रविष्टि चलती है। सभी वास्तविकता में, इस कथन में लगभग 85 आवेषण होंगे। – kentcdodds

6
मेरे सिर के ऊपर से

, कर सकते हैं स्ट्रिंग शाब्दिक के लिए 'क्यू' ऑपरेटर का उपयोग करने की कोशिश

जैसे

insert all 
    into domo_queries values (q'[select 
substr(to_char(max_data),1,4) as year, 
substr(to_char(max_data),5,6) as month, 
max_data 
from dss_fin_user.acq_dashboard_src_load_success 
where source = 'CHQ PeopleSoft FS']') 
select * from dual; 

नोट कुछ अपने विधेय के एकल उद्धरण से बच गया है कि नहीं कर रहे हैं, और स्ट्रिंग क्ष के बीच '[...]' बैठता है।

+0

बहुत बढ़िया, मैं 'क्यू' [] ''के बारे में भूल गया। पारितोषिक के लिए धन्यवाद! – kentcdodds

संबंधित मुद्दे