【问题标题】:How to pass table name to a Prepared Statement in a SELECT COUNT query? [duplicate]如何在 SELECT COUNT 查询中将表名传递给准备好的语句? [复制]
【发布时间】:2017-05-20 08:56:24
【问题描述】:

所以我有以下方法,效果很好:

static void getCount(final String url, final String username, final String password) throws SQLException {
    final Connection connection = DriverManager.getConnection(url, username, password);

    final String query = "SELECT COUNT(*) FROM app_user";
    final PreparedStatement preparedStatement = connection.prepareStatement(query);
    final ResultSet resultSet = preparedStatement.executeQuery();

    resultSet.next();
    System.out.println(resultSet.getInt(1));

    resultSet.close();
    preparedStatement.close();
    connection.close();
}

但是当我尝试时:

static void foobar(final String url, final String username, final String password, final String tablename) throws SQLException {
    final Connection connection = DriverManager.getConnection(url, username, password);

    final String query = "SELECT COUNT(*) FROM ? ";
    final PreparedStatement preparedStatement = connection.prepareStatement(query);
    preparedStatement.setString(1, tablename);
    final ResultSet resultSet = preparedStatement.executeQuery();

    resultSet.next();
    System.out.println(resultSet.getInt(1));

    resultSet.close();
    preparedStatement.close();
    connection.close();
}

我明白了:

Exception in thread "main" com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''app_user'' at line 1
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)

我做错了什么?

【问题讨论】:

    标签: java jdbc prepared-statement


    【解决方案1】:

    您只能绑定PreparedStatement 中的值,不能绑定语法元素或对象名称(在本例中为表名称)。您将不得不求助于字符串操作:

    final String query = String.format("SELECT COUNT(*) FROM %s", tablename);
    final PreparedStatement preparedStatement = connection.prepareStatement(query);
    final ResultSet resultSet = preparedStatement.executeQuery();
    

    请注意,此查询中没有占位符,因此与普通的旧 Statement 相比,使用 PreparedStatement 是否真的有任何优势值得怀疑。

    【讨论】:

    • 这是一个 SQL 注入漏洞。在此处插入鲍比桌玩笑
    • @TT 签名要求动态设置表名。机器人可以满足这些要求。
    猜你喜欢
    • 2015-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-18
    • 2015-08-25
    相关资源
    最近更新 更多