如何解决CREATE USER 和 CREATE ROLE 作为 PreparedStatement 使用 ?占位符
我试图以允许使用参数的方式从 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 ?;");
当然,我可以在没有 ?
的情况下组装我的字符串,方法是将值直接粘贴到语句中,尽管这会带来一些 sql 注入的可能性。
所以我想知道为什么占位符不起作用。这些声明是否完全支持它们?还是我错过了什么?
解决方法
一般情况下,数据库只允许 DML 中的参数,而不允许 DDL 中的参数。而在 DML 中,它只允许用于值。在 CREATE USER
和 CREATE ROLE
的情况下,您不处理值(至少不是用户或角色名称),因此无法对这些值进行参数化。这类似于在 select 语句中不允许使用表名或列名参数。
理论上,像 CREATE PASSWORD
中的密码是一个值并且可以参数化,但实际上这是不可能的(至少,我不知道),因为所有 DDL 都被处理作为不可参数化。
作为防止 SQL 注入的一种次要形式,自 JDBC 4.3(在 Java 9 中引入)以来,您可以使用 Statement.enquoteIdentifier
来引用标识符,并使用 Statement.enquoteLiteral
来表示密码等文字。这些方法有一个默认实现,但是如果您使用的是带有非标准标识符引号的平台(例如 MySQL),那么您必须确保它实际上被覆盖(在当前版本的 MySQL 连接器中不是这种情况/ J AFAIK)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。