我正在尝试使用PreparedStatement将记录插入到Oracle DB中,但仅收到此错误。在这一点上,我克服它的努力远远超过了我的进步,因此另一双眼睛可能会有所帮助。无效字符在哪里?

我发现的很多内容都表明,在SQL字符串中尾部的“ ; ”可能是罪魁祸首,但从一开始我就没有提到过。

我的连接本身,在程序的其他几个位置上都可以完美地实现:

Properties props = new Properties();
props.setProperty( "user", username );
props.setProperty( "password", password );
props.setProperty( "defaultRowPrefetch", "10" );
props.setProperty( "defaultBatchValue", "10" );
props.setProperty( "processEscapes", "false" );

DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
Connection conn = DriverManager.getConnection(DB_URL_SVC, props);

我想要完成的方式(除了我将它包装在接受三个String的方法中),但是它抛出 SQLSyntaxErrorException
String INSERT_BIKE = "INSERT INTO RACEBIKES ( BIKENAME , COUNTRY_OF_ORIGIN , COST ) VALUES ( ? , ? , ? )";
PreparedStatement preStatement = conn.prepareStatement( INSERT_BIKE );
preStatement.setString(1, "JHT");
preStatement.setString(2, "USA");
preStatement.setInt(3, 2500);
preStatement.executeUpdate();    // ORA-00911: invalid character error

可以使用,但是由于参数是硬编码的,因此无法使用PreparedStatement的目的:
String INSERT_BIKE = "INSERT INTO RACEBIKES ( BIKENAME , COUNTRY_OF_ORIGIN , COST ) VALUES ( 'JHT' , 'USA' , '2500' )";
PreparedStatement preStatement = conn.prepareStatement( INSERT_BIKE );
preStatement.executeUpdate();

适用于。但是,我知道用单引号和双引号连接变量并不是真正的最佳方法,因为PreparedStatement可以减轻我们不必处理语法的这一部分的麻烦:
String value1 = "JHT";
String value2 = "USA";
int value3 = 2500;
String INSERT_BIKE = "INSERT INTO RACEBIKES ( BIKENAME , COUNTRY_OF_ORIGIN , COST ) VALUES ( '" + value1 + "', '" + value2 + "', '" + value3 + "' )";
PreparedStatement preStatement = conn.prepareStatement( INSERT_BIKE );
preStatement.executeUpdate();

使用 SQLSyntaxErrorException 失败。因此,即使我自己使用代码引用语法,我仍然无法将这些变量放在preStatement.setString()中,这至少会带来一点灵活性。
String INSERT_BIKE = "INSERT INTO RACEBIKES ( BIKENAME , COUNTRY_OF_ORIGIN , COST ) VALUES ( ? , ? , ? )";
PreparedStatement preStatement = conn.prepareStatement( INSERT_BIKE );
preStatement.setString(1, "' + value1 + '");
preStatement.setString(2, "' + value2 + '");
preStatement.setInt(3, "' + value3 + '");
preStatement.executeUpdate();    // ORA-00911: invalid character error

失败。 将字符串中的占位符括在单引号中会导致 SQLException
String INSERT_BIKE = "INSERT INTO RACEBIKES ( BIKENAME , COUNTRY_OF_ORIGIN , COST ) VALUES ( '?' , '?' , '?' )";
PreparedStatement preStatement = conn.prepareStatement( INSERT_BIKE );
preStatement.setString(1, "JHT");
preStatement.setString(2, "USA");
preStatement.setInt(3, 2500);
preStatement.executeUpdate();    // invalid column index

失败。 用单引号将我的String中的两个String(但不是int)占位符括起来会导致 SQLException
String INSERT_BIKE = "INSERT INTO RACEBIKES ( BIKENAME , COUNTRY_OF_ORIGIN , COST ) VALUES ( '?' , '?' , ? )";
PreparedStatement preStatement = conn.prepareStatement( INSERT_BIKE );
preStatement.setString(1, "JHT");
preStatement.setString(2, "USA");
preStatement.setInt(3, 2500);
preStatement.executeUpdate();    // invalid column index

不会失败,但是也不会写入数据库(即使我尚未禁用自动提交)。
String INSERT_BIKE = "INSERT INTO RACEBIKES ( BIKENAME , COUNTRY_OF_ORIGIN , COST ) VALUES ( ? , ? , ? )";
PreparedStatement preStatement = conn.prepareStatement( INSERT_BIKE );
preStatement.setString(1, "JHT");
preStatement.setString(2, "USA");
preStatement.setInt(3, 2500);
preStatement.executeBatch();

我还尝试过使用反斜杠,双反斜杠,反引号和quitsies, no-startsies, erasies, double-stamps, and tofus-make-it-true进行转义的所有事项!也许有人知道可以帮助我的伏都教?

最佳答案

您为什么有props.setProperty( "processEscapes", "false" );是有原因的吗?

我相信这会关闭使用?作为绑定(bind)参数占位符的功能。我相信,如果启用了转义处理,则在将SQL字符串传递给Oracle之前,JDBC会对?占位符做一些“魔术”。否则,?字符将按原样发送到数据库。

有时会禁用转义处理。我在a previous answer中使用了一个涉及密码中?字符的问题。我相信可以在连接或语句级别禁用它;要在PreparedStatement上重新启用转义处理,请尝试调用preStatement.setEscapeProcessing(true);。我希望您的失败示例中的第一个能够成功使用此选项集。

至于您失败的示例,那些带有未转义?的示例将引起问题,因为?在SQL中不是有效字符。用单引号括起来的?会将其转换为单字符字符串,因此即使启用了转义处理,它也不是绑定(bind)参数。我不能说为什么最后一个不写到数据库。

09-26 16:53
查看更多