4

PreparedStatement を使用して Oracle DB にレコードを INSERT しようとしていますが、このエラーしか発生しません。この時点で、それを克服するための私の努力は私の進歩をはるかに上回っているので、別の目が役立つかもしれません. 無効な文字はどこにありますか?

私が見つけた多くのこと;は、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);

私がやりたい方法(3つの文字列を受け入れるメソッドでラップすることを除いて)ですが、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();

動作します。ただし、変数を一重引用符と二重引用符で連結することも、実際には最善の方法ではないことを理解しています。

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 内の 2 つのプレースホルダーString( ではない) を一重引用符で囲むと、 SQLExceptionが発生します。int

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" );か?

?これにより、バインド パラメーターのプレースホルダーとして使用する機能がオフになると思います。エスケープ処理が有効になっている場合、JDBC は?SQL 文字列を Oracle に渡す前に、プレースホルダーを使用して何らかの「魔法」を行うと思います。それ以外の場合、?文字はそのままデータベースに送信されます。

エスケープ処理を無効にする用途がときどきあります。パスワードに文字が含まれる質問への以前の回答で使用しました。?接続またはステートメントレベルで無効にできると思います。PreparedStatement でエスケープ処理を再度有効にするには、 を呼び出してみてくださいpreStatement.setEscapeProcessing(true);。失敗した最初の例は、このオプション セットで成功すると思います。

失敗した例については、エスケープされていない s を使用すると、SQL で有効な文字ではないため、?問題が発生します。シングルクォートで?囲むと1文字の文字列になるため、エスケープ処理を有効にしてもバインドパラメータにはなりません。?最後のものがデータベースに書き込まれない理由はわかりません。

于 2013-03-29T23:03:38.220 に答える