PreparedStatement:单引号上缺少表达式 (ORA-00936)
PreparedStatement: Missing expression on single quote (ORA-00936)
我正在这样查询 Oracle 数据库:
try (Connection c = dataSource.getConnection();
PreparedStatement p = c.prepareStatement(
"SELECT * FROM table WHERE column_string = ?")) {
p.setString(1, input);
try (ResultSet r = p.executeQuery()) {
// handle ResultSet
}
}
并且 input
字符串是从用户那里收到的。此调用适用于普通输入字符串,例如:
hello world
special: characters 0_2 (ftlo) -
但是对于这样的输入字符串失败:
7-8 l/o y-S '
(注意末尾的破折号、正斜杠和单引号)
我以为它与单引号有关,但我的印象是 PreparedStatement
会为您处理所有转义。有没有人见过这样的问题,或者更了解 oracle JDBC 驱动程序中的字符转义?
我正在使用:
- Java: 1.8.0_181
- Jboss:EAP 6.4.7.GA
- JDBC: ojdbc6 版本 11.2.0.3.0
- 数据库:Oracle 数据库 11g 企业版 11.2.0.4.0 版 - 64 位生产
堆栈跟踪:
SQLSyntaxErrorException: ORA-00936: missing expression
oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:445)
oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:879)
oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:450)
oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:192)
oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531)
oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:207)
oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:884)
oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1167)
oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1289)
oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3584)
oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3628)
oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1493)
org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeQuery(WrappedPreparedStatement.java:462)
... <my classes>
可能是单引号引起的问题,因为在 Oracle 中,最后一个必须重复两次才能输入为单引号,或者整个字符串必须包含在 q'{...}' 结构中,其中 ... 是给定的字符串.
无法重现。从 here 添加文件 ojdbc6-11.2.0.3.jar
。
运行 以下 MCVE 代码针对 12.1.0.2 服务器 (getConnection
的值当然被屏蔽了).
public static void main(String[] args) throws Exception {
test("hello world");
test("special: characters 0_2 (ftlo) -");
test("7-8 l/o y-S '");
test("X");
}
private static void test(String input) throws SQLException {
System.out.println(input);
try (Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@XXX:1521:XXX", "XXX", "XXX")) {
String sql = "select DUMMY from DUAL where DUMMY = ?";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, input);
try (ResultSet rs = stmt.executeQuery()) {
int count = 0;
while (rs.next()) {
System.out.println(" " + rs.getString("DUMMY"));
count++;
}
System.out.println(" " + count + " rows");
}
}
}
}
输出
hello world
0 rows
special: characters 0_2 (ftlo) -
0 rows
7-8 l/o y-S '
0 rows
X
X
1 rows
事实证明,我收到的错误代码与我想象的不同。在主查询完成后,我的 ResultSetHandler 正在执行一些额外的清理逻辑,这会抛出 SQLException(缺少表达式)。由于 apache DBults 和 JDBC 库的实施,错误被吞没并且没有以有用的方式打印出来。抱歉造成混淆。
我正在这样查询 Oracle 数据库:
try (Connection c = dataSource.getConnection();
PreparedStatement p = c.prepareStatement(
"SELECT * FROM table WHERE column_string = ?")) {
p.setString(1, input);
try (ResultSet r = p.executeQuery()) {
// handle ResultSet
}
}
并且 input
字符串是从用户那里收到的。此调用适用于普通输入字符串,例如:
hello world
special: characters 0_2 (ftlo) -
但是对于这样的输入字符串失败:
7-8 l/o y-S '
(注意末尾的破折号、正斜杠和单引号)
我以为它与单引号有关,但我的印象是 PreparedStatement
会为您处理所有转义。有没有人见过这样的问题,或者更了解 oracle JDBC 驱动程序中的字符转义?
我正在使用:
- Java: 1.8.0_181
- Jboss:EAP 6.4.7.GA
- JDBC: ojdbc6 版本 11.2.0.3.0
- 数据库:Oracle 数据库 11g 企业版 11.2.0.4.0 版 - 64 位生产
堆栈跟踪:
SQLSyntaxErrorException: ORA-00936: missing expression
oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:445)
oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:879)
oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:450)
oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:192)
oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531)
oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:207)
oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:884)
oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1167)
oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1289)
oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3584)
oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3628)
oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1493)
org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeQuery(WrappedPreparedStatement.java:462)
... <my classes>
可能是单引号引起的问题,因为在 Oracle 中,最后一个必须重复两次才能输入为单引号,或者整个字符串必须包含在 q'{...}' 结构中,其中 ... 是给定的字符串.
无法重现。从 here 添加文件 ojdbc6-11.2.0.3.jar
。
运行 以下 MCVE 代码针对 12.1.0.2 服务器 (getConnection
的值当然被屏蔽了).
public static void main(String[] args) throws Exception {
test("hello world");
test("special: characters 0_2 (ftlo) -");
test("7-8 l/o y-S '");
test("X");
}
private static void test(String input) throws SQLException {
System.out.println(input);
try (Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@XXX:1521:XXX", "XXX", "XXX")) {
String sql = "select DUMMY from DUAL where DUMMY = ?";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, input);
try (ResultSet rs = stmt.executeQuery()) {
int count = 0;
while (rs.next()) {
System.out.println(" " + rs.getString("DUMMY"));
count++;
}
System.out.println(" " + count + " rows");
}
}
}
}
输出
hello world
0 rows
special: characters 0_2 (ftlo) -
0 rows
7-8 l/o y-S '
0 rows
X
X
1 rows
事实证明,我收到的错误代码与我想象的不同。在主查询完成后,我的 ResultSetHandler 正在执行一些额外的清理逻辑,这会抛出 SQLException(缺少表达式)。由于 apache DBults 和 JDBC 库的实施,错误被吞没并且没有以有用的方式打印出来。抱歉造成混淆。