使用Prepared Statements设置表名

时间:2009-07-30 18:27:36

标签: java sql prepared-statement

我正在尝试使用预准备语句来设置表名以从中选择数据,但在执行查询时我一直收到错误。

错误和示例代码显示如下。

[Microsoft][ODBC Microsoft Access Driver] Parameter 'Pa_RaM000' specified where a table name is required.



private String query1 = "SELECT plantID, edrman, plant, vaxnode FROM [?]"; //?=date
public Execute(String reportDate){
    try {

        Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
        Connection conn = DriverManager.getConnection(Display.DB_MERC);
        PreparedStatement st = conn.prepareStatement(query1);
        st.setString(1, reportDate);
        ResultSet rs = st.executeQuery();

有关可能导致此问题的任何想法?

8 个答案:

答案 0 :(得分:31)

表名不能用作参数。它必须是硬编码的。所以你可以这样做:

private String query1 = "SELECT plantID, edrman, plant, vaxnode FROM [" + reportDate + "?]";

答案 1 :(得分:1)

这在技术上可行,但有一种解决方法,但实践非常糟糕。

String sql = "IF ? = 99\n";
sql += "SELECT * FROM first_table\n";
sql += "ELSE\n";
sql += "SELECT * FROM second_table";
PreparedStatement ps = con.prepareStatement(sql);

然后当你想从first_table中选择时,你可以用

设置参数
ps.setInt(1, 99);

如果没有,您可以将其设置为其他内容。

答案 2 :(得分:0)

正如许多人所说,你不能对表名使用语句参数,只能将变量用作条件的一部分。

基于你有一个带有(至少)两个表名的变量表名的事实,也许最好创建一个方法来获取你正在存储的实体并返回一个准备好的语句。

PreparedStatement p = createStatement(table);

答案 3 :(得分:0)

这可能会有所帮助:

public ResultSet getSomething(String tableName) {

PreparedStatement ps = conn.prepareStatement("select * from \`"+tableName+"\`");
ResultSet rs = ps.executeQuery();
}

答案 4 :(得分:0)

如果您需要一种不易受到SQL注入攻击的解决方案,则必须对所需的所有表重复查询:

final static String QUERIES = {
    "SELECT x FROM Table1 x WHERE a=:a AND b=:b AND ...",
    "SELECT x FROM Table2 x WHERE a=:a AND b=:b AND ...",
    "SELECT x FROM Table3 x WHERE a=:a AND b=:b AND ...",
    ...
};

是的:查询是重复的,只有表名不同。

现在,您只需选择适合您的表格的查询,例如喜欢

...
PreparedStatement st = conn.prepareStatement(QUERIES[index]);
...

您可以在JPA,Hibernate等任何方式下使用此方法...

如果您要使用更详细的方法,请考虑使用枚举之类的

enum AQuery {
    Table1("SELECT x FROM Table1 x WHERE a=:a AND b=:b AND ..."),
    Table2("SELECT x FROM Table2 x WHERE a=:a AND b=:b AND ..."),
    Table3("SELECT x FROM Table3 x WHERE a=:a AND b=:b AND ..."),
    ...

    private final String query;
    AQuery(final String query) {
        this.query = query;
    }

    public String getQuery() {
        return query;
    }
}

现在使用任一索引

String sql = AQuery.values()[index].getQuery();
PreparedStatement st = conn.prepareStatement(sql);
...

或使用表名

String sql = AQuery.valueOf("Table1").getQuery();
PreparedStatement st = conn.prepareStatement(sql);
...

答案 5 :(得分:-2)

我不确定您是否可以使用PreparedStatement来指定表的名称,只是指定某些字段的值。无论如何,你可以尝试相同的查询,但没有括号:

"SELECT plantID, edrman, plant, vaxnode FROM ?"

答案 6 :(得分:-2)

String table="pass"; 

String st="select * from " + table + " ";

PreparedStatement ps=con.prepareStatement(st);

ResultSet rs = ps.executeQuery();

答案 7 :(得分:-3)

有一种方法可以将表名作为变量传递

String NameOfTable =" test.Employee&#34 ;;

String Fquery =" SELECT * FROM" + NameOfTable +" Done =' No'";

注意: 在FROM和后续的#34;之间应该有一个空格。以及"之间以及关键字