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

发布于 2024-07-29 22:17:10 字数 629 浏览 4 评论 0原文

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

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

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

有什么想法可能导致这种情况吗?

I'm trying to use prepared statements to set a table name to select data from, but I keep getting an error when I execute the query.

The error and sample code is displayed below.

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

Any thoughts on what might be causing this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

戏蝶舞 2024-08-05 22:17:24
String table="pass"; 

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

PreparedStatement ps=con.prepareStatement(st);

ResultSet rs = ps.executeQuery();
String table="pass"; 

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

PreparedStatement ps=con.prepareStatement(st);

ResultSet rs = ps.executeQuery();
小姐丶请自重 2024-08-05 22:17:22

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

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

I'm not sure you can use a PreparedStatement to specify the name of the table, just the value of some fields. Anyway, you could try the same query but, without the brackets:

"SELECT plantID, edrman, plant, vaxnode FROM ?"
浴红衣 2024-08-05 22:17:21

这可能有帮助:

public ResultSet getSomething(String tableName) {

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

This might help:

public ResultSet getSomething(String tableName) {

PreparedStatement ps = conn.prepareStatement("select * from \`"+tableName+"\`");
ResultSet rs = ps.executeQuery();
}
歌入人心 2024-08-05 22:17:20

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

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

PreparedStatement p = createStatement(table);

As a number of people have said, you can't use a statement parameter for a table name, only for variables as part of the condition.

Based on the fact you have a variable table name with (at least) two table names, perhaps it would be best to create a method which takes the entity you are storing and returns a prepared statement.

PreparedStatement p = createStatement(table);
墨落成白 2024-08-05 22:17:18

这在技术上可以通过解决方法实现,但是非常糟糕的做法。

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

或者如果没有,则将其设置为其他值。

This is technically possible with a workaround, but very bad practice.

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

And then when you want to select from first_table you set the parameter with

ps.setInt(1, 99);

Or if not, you set it to something else.

王权女流氓 2024-08-05 22:17:17

您无法在准备好的语句中设置表名称

如前所述,不可能在准备好的语句中使用 preparedStatement.setString(1, tableName) 设置表名称。 而且也不可能将部分 SQL 查询添加到准备好的语句中(例如 preparedStatement.addSql(" or xyz is null"))。

如何正确地做到这一点而不冒 SQL 注入的风险?

表名必须插入到要使用字符串操作执行的 SQL(或 JQL)查询中,例如 "select * from " + tableNameString.format("select * from %s ", tableName)

但是如何避免SQL注入呢?

如果表名称不是来自用户输入,那么您可能安全
例如,如果您做出如下决定,

String tableName;
if(condition) {
    tableName = "animal";
} else {
    tableName = "plant";
}
final String sqlQuery = "delete from " + tableName;
...

如果表名称取决于用户输入,则您需要手动检查输入。
例如,使用包含所有有效表名称的白名单

if(!tableNamesWhitelist.contains(tableName)) {
    throw new IllegalArgumentException(tableName + " is not a valid table name");
}
String sqlQuery = "delete from " + tableName;

或使用枚举

public enum Table {
    ANIMAL("animal"),
    PLANT("plant");

    private sqlTableName;
    private TableName(String sqlTableName) {
        this.sqlTableName= sqlTableName;
    }
    public getSqlTableName() {
        return sqlTableName;
    }
}

然后转换用户输入字符串,例如ANIMAL进入Table.ANIMAL。 如果不存在合适的枚举值,则会引发异常。

例如,

@DeleteMapping("/{table}")
public String deleteByEnum(@PathVariable("table") Table table) {
    final String sqlQuery = "delete from " + table.getSqlTableName();
    ...
}

当然,这些示例也可以与选择、更新等一起使用,并且可以使用许多其他实现来检查用户输入。

You can't set table name in prepared statement

As said before, it is not possible to set the table name in a prepared statement with preparedStatement.setString(1, tableName). And it is also not possible to add parts of the SQL query to a prepared statement (eg preparedStatement.addSql(" or xyz is null")).

How to do it right without risking SQL injections?

The table name must be inserted into the SQL (or JQL) query you want to execute with string operations like "select * from " + tableName or String.format("select * from %s", tableName)

But how to avoid SQL injections?

If the table name does not come from user input, you are probably safe.
For example, if you make a decision like here

String tableName;
if(condition) {
    tableName = "animal";
} else {
    tableName = "plant";
}
final String sqlQuery = "delete from " + tableName;
...

If the table name depends on the users input, you need to check the input manually.
For example, with a white-list containing all valid table names:

if(!tableNamesWhitelist.contains(tableName)) {
    throw new IllegalArgumentException(tableName + " is not a valid table name");
}
String sqlQuery = "delete from " + tableName;

or with an enum:

public enum Table {
    ANIMAL("animal"),
    PLANT("plant");

    private sqlTableName;
    private TableName(String sqlTableName) {
        this.sqlTableName= sqlTableName;
    }
    public getSqlTableName() {
        return sqlTableName;
    }
}

and then convert the user-input string like ANIMAL into Table.ANIMAL. An exception is thrown, if no fitting enumeration value does exist.

eg

@DeleteMapping("/{table}")
public String deleteByEnum(@PathVariable("table") Table table) {
    final String sqlQuery = "delete from " + table.getSqlTableName();
    ...
}

Of course these examples work with select, update, ... too and a lot of other implementations to check the user input are possible.

亣腦蒛氧 2024-08-05 22:17:13

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

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

A table name can't be used as a parameter. It must be hard coded. So you can do something like:

private String query1 = "SELECT plantID, edrman, plant, vaxnode FROM [" + reportDate + "?]";
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文