微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

CREATE USER 和 CREATE ROLE 作为 PreparedStatement 使用 ?占位符

如何解决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 USERCREATE ROLE 的情况下,您不处理值(至少不是用户或角色名称),因此无法对这些值进行参数化。这类似于在 select 语句中不允许使用表名或列名参数。

理论上,像 CREATE PASSWORD 中的密码是一个值并且可以参数化,但实际上这是不可能的(至少,我不知道),因为所有 DDL 都被处理作为不可参数化。

作为防止 SQL 注入的一种次要形式,自 JDBC 4.3(在 Java 9 中引入)以来,您可以使用 Statement.enquoteIdentifier 来引用标识符,并使用 Statement.enquoteLiteral 来表示密码等文字。这些方法有一个默认实现,但是如果您使用的是带有非标准标识符引号的平台(例如 MySQL),那么您必须确保它实际上被覆盖(在当前版本的 MySQL 连接器中不是这种情况/ J AFAIK)。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。