Java SQLSyntaxErrorException:ORA-00911:无效字符

Java SQLSyntaxErrorException:ORA-00911:无效字符,java,sql,database,oracle,jdbc,Java,Sql,Database,Oracle,Jdbc,我试图使用PreparedStatement将记录插入到Oracle数据库中,但我只收到此错误。在这一点上,我克服它的努力远远超过了我的进步,所以另一双眼睛可能会有所帮助。无效字符在哪里 我发现的很多东西表明,sql字符串中的尾随“;”可能是罪魁祸首,但我从一开始就没有在我的语句中找到 我的连接本身,在程序中的其他几个位置都能完美地工作: Properties props = new Properties(); props.setProperty( "user", username ); pro

我试图使用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
失败。用单引号括住我的字符串中的占位符将导致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.executeUpdate();    // invalid column index
失败。将我的字符串中的两个
字符串
(但不是
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.executeUpdate();    // invalid column index
这个不会失败,但也不会写入数据库(即使我没有禁用自动提交)


我也试过用反斜杠,双反斜杠,反斜杠来逃避!也许有人知道巫毒会帮助我

为什么要使用
props.setProperty(“processEscapes”、“false”)

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

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


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

为了使用
executeBatch()
,您需要先调用
addBatch()
(针对每一行)。我想它也会失败。让我印象深刻的是,您的第三个参数是int,但在您的工作示例中,您也使用单引号。如果你不考虑他们会怎么样?如果这也不起作用,我假设你的
COST
列也是
VARCHAR
。啊,是的,我忘了在我原来的帖子中包括这个案例。使用executeBatch()更像是在黑暗中拍摄,因为我在properties对象中设置了batchValue。在这种情况下,用户一次只能更新一条记录。但是在executeBatch()上面包含addBatch()仍然会导致BatchUpdateException:ORA-00911:无效字符。
成本
列是一个
数字
,但是删除单引号会抛出ORA-00911。您的意思是,执行
“插入赛车(自行车名称,原产国,成本)值('JHT','USA',2500)”
是否也会导致ORA-00911?请将您的第一个(原始)代码片段更改为:
preStatement.setString(3,“2500”)然后再试一次?但是为什么
插入到赛车(比基尼名称、原产国、成本)值('JHT'、'USA',2500)
失败了?非常好!调用
preStatement.setEscapeProcessing(true)是答案。我将它设置为false,因为在其他一些地方,我使用这个实例进行一些硬编码查询,而这些查询不需要转义处理。在这些情况下,我认为省略这些调用更有效,但从未想到这也会阻止我按预期使用PreparedStatement,非常感谢您的洞察力@你指的是哪个例子?我不明白你在评论中输入的SQL为什么会失败。@es0329:很高兴听到我的答案有帮助。我不能说禁用转义处理是否会大大提高性能(老实说,如果它真的提高了性能,我会感到惊讶),但找到答案的唯一方法是对其进行基准测试。数据库运行硬编码查询所需的时间,一次启用转义处理,一次禁用转义处理,看看两次运行之间的时间差是多少。@LukeWoodward:我指的是第二个示例的一个微小变化-在
2500
左右删除单引号。es0329也因此获得了ORA-00911。即使关闭了转义处理,我也不明白为什么会失败。你有什么想法吗?