Teradata JDBC无法将PreparedStatement参数识别为没有引号的VARCHAR

时间:2016-11-30 19:03:27

标签: java jdbc prepared-statement teradata setstring

我正在使用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参数吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

您是否尝试过String myPhoneNumber = "'5551234567'";

注意 - 包含单引号以包装值。

如果您查看Teradata手册here中的示例,您将看到查询频段的设置方式与OP的第一个示例按预期方式相同,而不会使用单引号将其包装起来。在我看来,OP的第一个例子中的这种行为是预期的。

修改 Teradata为其JDBC驱动程序提供的示例代码使用java.sql.PreparedStatment。有了这个,他们的示例程序使用setString而没有任何技巧来为INSERT语句提供字符串值。 Sample Code如果您无法复制该行为,我会打开Teradata GSC的事件。