我正在使用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參數嗎?
謝謝!
這似乎很奇怪。 – Kayaman
SetString不會在您的參數周圍添加引號。從連接角度來考慮它。如果您對'select * from ... where phone_number ='和myPhoneNumber進行連接,則最終會出現'where phone_number = 5551234567'。它正在做你正在問的問題。 Teradata沒有失敗,而是默默地做了一個(非常昂貴的)隱式演員。 – Andrew
@Andrew它不應該*有*。無論在線二進制格式是什麼,都應該根據設置的參數類型來構造。引用是爲了人類的可讀性,數據庫不需要它們。 – Kayaman