2013-07-11 72 views
1

我正在使用JDBC连接到Servlet中的数据库(Oracle10)。
以下是我想要动态设置三个参数的查询。oracle异常:表名无效

  1. 表名
  2. 列名
  3. 价值

查询:

query = "select ? from ? where ? = ?"; 
mypstmt = con.prepareStatement(query); 
mypstmt.setString(1, tableName); 
mypstmt.setString(2, columnName); 
mypstmt.setString(3, columnName2); 
mypstmt.setString(4, value); 

但上面的查询是给我的错误:

java.sql.SQLException: ORA-00903: invalid table name 

我检查了表名。它是正确的,如果我写这样的查询:

query = "select "+columnName+" from "+tableName+" where "+columnName2+" = ?"; 

然后它执行正常。

所以,我应该怎么做,如果我想设置Table nameColumn Namesmypstmt.setString(1,tableName)

EDIT1 我为什么要parameterizeTable nameColumn name是我允许用户选择/输入表的原因名称和列名,所以我想避免SQL Injection

回答

4

我们无法直接将表名传递给PreparedStatement,因为表名不能是绑定变量。 PreparedStatement

An object that represents a precompiled SQL statement.

A SQL statement is precompiled and stored in a PreparedStatement object. This object can then be used to efficiently execute this statement multiple times.

您必须构建带字符串连接的sql。使用存储过程,您可以使用Dynamic SQL动态地传递表名。甚至看看this SO answer了解为什么它受到限制。

+0

列名可以使用'PreparedStatement'作为参数传递吗? – user75ponic

+1

@Polppan - no。只有值可以作为参数传递。 (否则,SQL引擎将无法预先编译/计划准备好的语句,并且您有更多的注入攻击范围等) –

+0

否................. ..... – NINCOMPOOP

2

您只能在SQL查询中参数化?列值。表/列参数化是不可能的,而是使用变量来构造这样的查询,例如:

void query(String tableName, String columnName, String queryColumnName String val) { 
String query = "select "+columnName+" from "+tableName+" where "+queryColumnName+" = ?"; 
mypstmt.setString(1, val); 
.. 
} 
1

在的PreparedStatement只能替换值。你不能替换表名或列名。