0

私は以下を使用して準備されたステートメントを実行しようとしています:

dbaBean.setPrepStmt(dbaBean.getConn().prepareStatement(
    "SELECT id, author, title, url, article_text, date_created " +
            "FROM articles WHERE " +
            "(EXTRACT(YEAR FROM date_created) = ? OR ? is null) " +
            "AND (EXTRACT(MONTH FROM date_created) = ? OR ? is null) " +
            "AND (EXTRACT(DAY FROM date_created) = ? OR ? is null) AND " +
            "(url = ? OR ? is null) " +
            "ORDER BY date_created DESC;"));

dbaBean.getPrepStmt().setString(1, year);
dbaBean.getPrepStmt().setString(2, year);
dbaBean.getPrepStmt().setString(3, month);
dbaBean.getPrepStmt().setString(4, month);
dbaBean.getPrepStmt().setString(5, day);
dbaBean.getPrepStmt().setString(6, day);
dbaBean.getPrepStmt().setString(7, URL);
dbaBean.getPrepStmt().setString(8, URL);

System.out.println(dbaBean.getPrepStmt().toString());

dbaBeanは、接続と準備されたステートメントを提供するオブジェクトです。操作は一切行いません。

私は上記のコードを他のメソッドに非常にうまく使用しましたが、まったく問題はありませんでした。これで、この関数は最後にセミコロンを削除しているように見えます。たとえば、これはSystem.out行で出力されます。

SELECT id, author, title, url, article_text, date_created FROM articles WHERE (EXTRACT(YEAR FROM date_created) = NULL OR NULL is null) AND (EXTRACT(MONTH FROM date_created) = NULL OR NULL is null) AND (EXTRACT(DAY FROM date_created) = NULL OR NULL is null) AND (url = 'someurl' OR 'someurl' is null) ORDER BY date_created desc

セミコロンがないことに注意してください。

2番目のセミコロンを追加しようとしましたが、それも「食べられました」。

他の変更はうまく伝播されます(たとえば、選択する別のフィールド)。

それが重要な場合、これはpostgresqlです。

編集:このクエリの実行中にエラーが発生し、セミコロンの削除が潜在的な原因であると考えたため、気にしています。以下の答えは、これが当てはまらないことを示しているようであり、私はそれを他の場所で探す必要があります。

4

2 に答える 2

4

Postgresql JDBCドライバーのソースコードを数分間トロールしましたが、次のように表示されます。

  • プリペアドステートメントが作成されると、ドライバーは部分的な解析を実行してSQLをステートメントに分割し、プレースホルダーを見つけて(私は)コメントを削除します。

  • 解析の結果は、PreparedStatementフラグメントのシーケンスをオブジェクトに格納します。

  • ステートメントを呼び出すtoString()と、メソッドはSQLを再構築し、プレースホルダーの値を挿入し、各ステートメントの間にセミコロンを追加します...複数のステートメントがある場合。

したがって、セミコロンの消失は機能であり、バグではありません。JDBC仕様には、toString()メソッドが元の形式でクエリを提供することを要求するものはありません...または任意の形式で。さらに、SQL for JDBCを作成するときに、(少なくともPostgresqlでは)末尾のセミコロンを省略して使用するのが通常の方法です。

于 2012-06-06T13:18:00.243 に答える
3

preparedStatement(String sql)メソッドは入力文字列を受け取り、CallableStatementデータベースのストアドプロシージャを呼び出すためのオブジェクトを作成します。

CallableStatementオブジェクトの初期化中に、SQL文字列はjdbcドライバーによってシステムのネイティブSQL文法に変換されます。

セミコロンはPostgresqlの区切り文字であるため、jdbcドライバーによって削除され、他のjdbcドライバーの実装を使用している場合は異なる可能性があると想定できます。したがって、最善の策は、SQL文字列からそれを削除することです。

于 2012-06-06T12:43:45.580 に答える