创建数据库模式时是否可以使用Java中的Prepared Statement?

bob*_*e01 5 java sql database prepared-statement

如果没有,是否有比字符串连接更安全的方法?

试过这个..

final String CREATE_SCHEMA_SQL = "CREATE SCHEMA IF NOT EXISTS ?";
List<String> schemas = // ["001", "002", "003"];

for (String schema : schemas) {

  try (Connection connection = dataSource.getConnection();
      PreparedStatement createSchemaStatement =
          connection.prepareStatement(CREATE_SCHEMA_SQL)) {

    createSchemaStatement.setString(1, schema);
    createSchemaStatement.executeUpdate();
    
  } catch (SQLException e) {
    throw new RuntimeException("Could not create tenant schema");
  }
}
Run Code Online (Sandbox Code Playgroud)

产生这个错误:

org.postgresql.util.PSQLException: ERROR: syntax error at or near "$1"
  Position: 29
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2674)
Run Code Online (Sandbox Code Playgroud)

Mih*_*ihe 0

除了在服务器端使用动态 SQL 之外,您还可以使用 PostgreSQL 的格式函数对标识符进行编码来查询 create 语句。

例如:

private String getCreateSchemaStatement(Connection conn, String schemaName) throws SQLException {
    String sql = "SELECT format('CREATE SCHEMA IF NOT EXISTS %I', ?)";
    try (PreparedStatement stmt = conn.prepareStatement(sql)) {
        stmt.setString(1, schemaName);
        return getSingleResultString(stmt);
    }
}

private String getSingleResultString(PreparedStatement stmt) throws SQLException {
    try (ResultSet rs = stmt.executeQuery()) {
        String result = null;
        if (rs.next()) {
            result = rs.getString(1);
        }
        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

有了这个,你就可以执行语句:

public void createSchemas(List<String> schemaNames) throws SQLException {
    try (Connection conn = dataSource.getConnection();
         Statement stmt = conn.createStatement()) {
        for (String schemaName : schemaNames) {
            String sql = getCreateSchemaStatement(conn, schemaName);
            stmt.execute(sql);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,如果已知模式名称是安全的,则不需要这样做。