SQLSyntaxErrorException:ORA-00911:无效字符

时间:2013-03-29 21:20:13

标签: java sql database oracle jdbc

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

我发现的很多内容都表明你的sql String中的尾随“ ; ”可能是罪魁祸首,但我的陈述中没有一个一开始。

我的连接本身,在程序中的其他几个位置完美地工作

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(但不是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的逃生问题!也许有人在那里知道会帮助我的伏都教?!

1 个答案:

答案 0 :(得分:4)

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

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

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

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