我正在使用JDBC PreparedStatement从Web服务查询Teradata数据库。我的表有一个PHONE_NUMBER列,存储为VARCHAR(10)。我一直使用PreparedStatement setString()
为此列提供参数,如下所示:
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
进行比较。以下是EXPLAIN计划的摘录:
...
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参数吗?
谢谢!
答案 0 :(得分:0)
您是否尝试过String myPhoneNumber = "'5551234567'";
注意 - 包含单引号以包装值。
如果您查看Teradata手册here中的示例,您将看到查询频段的设置方式与OP的第一个示例按预期方式相同,而不会使用单引号将其包装起来。在我看来,OP的第一个例子中的这种行为是预期的。
修改强>
Teradata为其JDBC驱动程序提供的示例代码使用java.sql.PreparedStatment
。有了这个,他们的示例程序使用setString
而没有任何技巧来为INSERT
语句提供字符串值。 Sample Code如果您无法复制该行为,我会打开Teradata GSC的事件。