CREATE USER 和 CREATE ROLE 作为 PreparedStatement with ?占位符
CREATE USER and CREATE ROLE as PreparedStatement with ? placeholder
我正在尝试以允许使用参数的方式从 Java 代码针对 HSQLDB 数据库发出 CREATE USER
语句。
然而,下面一行:
connection.prepareStatement("CREATE USER ? PASSWORD ?;");
抛出异常:
java.sql.SQLSyntaxErrorException: unexpected token: ? in statement [CREATE USER ? PASSWORD ?;]
at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
at org.hsqldb.jdbc.JDBCPreparedStatement.<init>(Unknown Source)
at org.hsqldb.jdbc.JDBCConnection.prepareStatement(Unknown Source)
at (somewhere in my code)
也是如此
connection.prepareStatement("CREATE ROLE ?;");
当然,我可以 assemble 我的字符串而不 ?
,方法是将值直接粘贴到语句中,尽管这会打开一些 SQL 注入的可能性。
所以我想知道为什么占位符不起作用。这些声明完全支持它们吗?还是我漏掉了什么?
一般情况下,数据库只允许DML 中的参数,不允许DDL 中的参数。而在 DML 中,只允许 values。在 CREATE USER
和 CREATE ROLE
的情况下,您不是在处理值(至少不是用户或角色名称),因此参数化对它们来说是不可能的。这类似于在 select 语句中不允许 table 名称或列名称的参数。
理论上,CREATE PASSWORD
中的密码之类的东西是一个值,可以参数化,但实际上这是不可能的(至少,我不知道),因为所有 DDL被处理为不可参数化。
作为针对 SQL 注入的一种次要保护形式,自 JDBC 4.3(在 Java 9 中引入)以来,您可以将 Statement.enquoteIdentifier
to quote identifiers, and Statement.enquoteLiteral
用于密码等文字。这些方法有一个默认实现,但如果您使用的平台带有非标准标识符引号(例如 MySQL),那么您必须确保它确实被覆盖(当前版本不是这种情况) MySQL Connector/J AFAIK)。
我正在尝试以允许使用参数的方式从 Java 代码针对 HSQLDB 数据库发出 CREATE USER
语句。
然而,下面一行:
connection.prepareStatement("CREATE USER ? PASSWORD ?;");
抛出异常:
java.sql.SQLSyntaxErrorException: unexpected token: ? in statement [CREATE USER ? PASSWORD ?;]
at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
at org.hsqldb.jdbc.JDBCPreparedStatement.<init>(Unknown Source)
at org.hsqldb.jdbc.JDBCConnection.prepareStatement(Unknown Source)
at (somewhere in my code)
也是如此
connection.prepareStatement("CREATE ROLE ?;");
当然,我可以 assemble 我的字符串而不 ?
,方法是将值直接粘贴到语句中,尽管这会打开一些 SQL 注入的可能性。
所以我想知道为什么占位符不起作用。这些声明完全支持它们吗?还是我漏掉了什么?
一般情况下,数据库只允许DML 中的参数,不允许DDL 中的参数。而在 DML 中,只允许 values。在 CREATE USER
和 CREATE ROLE
的情况下,您不是在处理值(至少不是用户或角色名称),因此参数化对它们来说是不可能的。这类似于在 select 语句中不允许 table 名称或列名称的参数。
理论上,CREATE PASSWORD
中的密码之类的东西是一个值,可以参数化,但实际上这是不可能的(至少,我不知道),因为所有 DDL被处理为不可参数化。
作为针对 SQL 注入的一种次要保护形式,自 JDBC 4.3(在 Java 9 中引入)以来,您可以将 Statement.enquoteIdentifier
to quote identifiers, and Statement.enquoteLiteral
用于密码等文字。这些方法有一个默认实现,但如果您使用的平台带有非标准标识符引号(例如 MySQL),那么您必须确保它确实被覆盖(当前版本不是这种情况) MySQL Connector/J AFAIK)。