Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用准备好的语句设置表名_Java_Sql_Prepared Statement - Fatal编程技术网

Java 使用准备好的语句设置表名

Java 使用准备好的语句设置表名,java,sql,prepared-statement,Java,Sql,Prepared Statement,我试图使用prepared语句设置表名以从中选择数据,但在执行查询时不断出现错误 错误和示例代码如下所示 [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 publ

我试图使用prepared语句设置表名以从中选择数据,但在执行查询时不断出现错误

错误和示例代码如下所示

[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();

您是否知道是什么原因导致了这种情况?

不能将表名用作参数。它必须是硬编码的。因此,您可以执行以下操作:

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

表名不能用作参数。它必须是硬编码的。因此,您可以执行以下操作:

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

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

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

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

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

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

基于您有一个包含(至少)两个表名的变量表名这一事实,最好创建一个方法,该方法接受您存储的实体并返回一个准备好的语句

PreparedStatement p = createStatement(table);

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

基于您有一个包含(至少)两个表名的变量表名这一事实,最好创建一个方法,该方法接受您存储的实体并返回一个准备好的语句

PreparedStatement p = createStatement(table);

这在技术上是可行的,但实际上非常糟糕

String sql = "IF ? = 99\n";
sql += "SELECT * FROM first_table\n";
sql += "ELSE\n";
sql += "SELECT * FROM second_table";
PreparedStatement ps = con.prepareStatement(sql);
然后,当您要从第一个_表中选择时,可以使用

ps.setInt(1, 99);

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

这在技术上是可行的,但实践非常糟糕

String sql = "IF ? = 99\n";
sql += "SELECT * FROM first_table\n";
sql += "ELSE\n";
sql += "SELECT * FROM second_table";
PreparedStatement ps = con.prepareStatement(sql);
然后,当您要从第一个_表中选择时,可以使用

ps.setInt(1, 99);
否则,您可以将其设置为其他设置。

这可能会有帮助:

public ResultSet getSomething(String tableName) {

PreparedStatement ps = conn.prepareStatement("select * from \`"+tableName+"\`");
ResultSet rs = ps.executeQuery();
}
这可能有助于:

public ResultSet getSomething(String tableName) {

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

如果需要一个不易受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,比如

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);
...

如果需要一个不易受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,比如

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);
...


在查询中,您需要用括号来转义“/”,或者可能是日期。我去年夏天查过了,在查询中需要括号来转义“/”,或者可能是日期。我去年夏天查过了是的,输入净化是为了防止SQL注入!如果需要将不同的表名替换为具有相同结构的查询,则表明数据库设计中存在缺陷。至少它指向具有相同关系属性的多个表。将其规范化为一个带有“subject”列的表。是的,输入清理以防止SQL注入!如果需要将不同的表名替换为具有相同结构的查询,则表明数据库设计中存在缺陷。至少它指向具有相同关系属性的多个表。将其规范化为一个带有“主题”列的表。您能否为您的答案提供一些上下文,这样未来的读者就可以了解如何将其应用于他们的问题,而不仅仅是在这种情况下。易受SQL注入的影响。不要这样做!您能否为您的答案提供一些上下文,这样未来的读者就可以了解如何将其应用于他们的问题,而不仅仅是在这种情况下。易受SQL注入攻击。不要这样做!不!这是由于表名上的SQL-injection.use
org.apache.commons.lang.StringEscapeUtils.escapeSql
导致的安全问题,以确保您不会将架构置于风险中。@所有建议表名的字符串串联的人:不要这样做。这让位于SQL注入——OWASPs Top 10中的头号攻击(请参阅)不言而喻,如果要这样做,那么必须将表名列入白名单(并且您应该使用白名单中的值,而不是输入的值,只是为了确保;regex等)不要使用
org.apache.commons.lang.StringEscapeUtils.escapeSql
。它在commons.lang3中被弃用,并且在任何情况下都只能用双单引号替换单引号。它不会阻止SQL注入。看,别!这是由于表名上的SQL-injection.use
org.apache.commons.lang.StringEscapeUtils.escapeSql
导致的安全问题,以确保您不会将架构置于风险中。@所有建议表名的字符串串联的人:不要这样做。这让位于SQL注入——OWASPs Top 10中的头号攻击(请参阅)不言而喻,如果要这样做,那么必须将表名列入白名单(并且您应该使用白名单中的值,而不是输入的值,只是为了确保;regex等)不要使用
org.apache.commons.lang.StringEscapeUtils.escapeSql
。它在commons.lang3中被弃用,并且在任何情况下都只能用双单引号替换单引号。它不会阻止SQL注入。见和。