2016-11-30 26 views
0

我正在使用JDBC PreparedStatement從Web服務查詢Teradata數據庫。我的表有一個PHONE_NUMBER列,存儲爲VARCHAR(10)。我一直用PreparedStatement setString()提供參數此列,如下圖所示:Teradata JDBC無法將不帶引號的VARCHAR識別爲PreparedStatement參數

String myPhoneNumber = "5551234567";  
String sql = "SELECT * FROM MYTABLE " + 
      "WHERE PHONE_NUMBER = ? "; 
PreparedStatement p_stmt = db.getPreparedStatement(sql); 
p_stmt.setString(1, myPhoneNumber); 
ResultSet rs = db.executeQuery(p_stmt); 

它返回正確的結果,但我注意到Teradata的是使用該查詢的CPU是相當高的。根據EXPLAIN計劃,Teradata似乎將myPhoneNumber參數解釋爲FLOAT而不是VARCHAR,因此它必須執行數據轉換才能將其與VARCHAR列PHONE_NUMBER進行比較。下面是說明計劃的摘錄:

... 
MYDATABASE.MYTABLE.PHONE_NUMBER (FLOAT, FORMAT 
'-9.99999999999999E-999'))= 5.55123456700000E 009) 

所以,我想出了下面的,這表明在CPU使用率(99.86%提高)有很大的改進:

String myPhoneNumber = "5551234567";  
String sql = "SELECT * FROM MYTABLE " + 
      "WHERE PHONE_NUMBER = ''||?||'' "; 
PreparedStatement p_stmt = db.getPreparedStatement(sql); 
p_stmt.setString(1, myPhoneNumber); 
ResultSet rs = db.executeQuery(p_stmt); 

所以我的問題是爲什麼這是必要的? setString不應該告訴JDBC告訴Teradata期望String/VARCHAR參數嗎?

謝謝!

+1

這似乎很奇怪。 – Kayaman

+0

SetString不會在您的參數周圍添加引號。從連接角度來考慮它。如果您對'select * from ... where phone_number ='和myPhoneNumber進行連接,則最終會出現'where phone_number = 5551234567'。它正在做你正在問的問題。 Teradata沒有失敗,而是默默地做了一個(非常昂貴的)隱式演員。 – Andrew

+2

@Andrew它不應該*有*。無論在線二進制格式是什麼,都應該根據設置的參數類型來構造。引用是爲了人類的可讀性,數據庫不需要它們。 – Kayaman

回答

0

你試過String myPhoneNumber = "'5551234567'";

注意 - 單引號列入包裹的價值。

如果您查看Teradata手冊here中的示例,您會發現查詢波段的設置方式與OP的第一個示例按照預期方式設置的方式相同,而沒有單引號將其包裝。在我看來,在OP的第一個例子中,這種行爲是可以預料的。

編輯 Teradata爲其JDBC驅動程序提供的示例代碼是使用java.sql.PreparedStatment。通過這個例子,程序使用setString而沒有任何技巧爲INSERT語句提供字符串值。 Sample Code如果您無法複製該行爲,我將使用Teradata GSC開啓一個事件。

+1

這不是參數應該如何工作,它看起來與JDBC和SQL標準高度不兼容。 –

+0

你說得對。看起來Teradata的JDBC驅動程序不像預期的那樣運行。 –

+0

根據評論和更多研究編輯回答 –