4

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

我发现的很多内容表明,;你的 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);

我想要完成它的方式(除了我会将它包装在一个接受三个字符串的方法中)但它会抛出一个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

失败。用单引号将占位符括在我的 String 中会导致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 和 tofus-make-it-true 的转义问题!也许有人知道会帮助我的巫毒教?!

4

1 回答 1

5

你有理由props.setProperty( "processEscapes", "false" );吗?

I believe that this turns off the ability to use ? as bind parameter placeholder. I believe that if escape processing is enabled, JDBC does some 'magic' with the ? placeholders before passing the SQL string to Oracle. Otherwise, the ? character is sent to the database as-is.

There are occasional uses for disabling escape processing. I used it in a previous answer to a question involving ? characters in passwords. I believe it can be disabled at the connection or the statement level; to re-enable escape processing on a PreparedStatement, try calling preStatement.setEscapeProcessing(true);. I would expect the first of your failing examples to succeed with this option set.

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

于 2013-03-29T23:03:38.220 回答