我正在使用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