Java 如何在SELECT COUNT查询中将表名传递给准备好的语句?

Java 如何在SELECT COUNT查询中将表名传递给准备好的语句?,java,jdbc,prepared-statement,Java,Jdbc,Prepared Statement,所以我有以下的方法,效果很好: 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

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

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)

我做错了什么?

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

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

请注意,此查询中没有占位符,因此使用
PreparedStatement
与普通的
语句相比是否真的有任何优势值得怀疑,因为这是一个SQL注入漏洞。在此处插入bobby tables笑话@TT签名要求动态设置表名。对于这些要求,您可以做很多事情。