2016-08-25 3 views
0

に終了していない私は、このクエリを持っている:ORA-00933:SQLコマンドが正常にJDBC呼び出し

SELECT col FROM table WHERE 
last_updated > SYS_EXTRACT_UTC(systimestamp) - INTERVAL ? DAY TO SECOND(1) 

と私のDBアクセスコードで、

stmt.setString(1, "0 00:01:30.0");//stmt is OraclePreparedStatement 
rs = stmt.executeQuery();//results in exception 

例外メッセージ:java.sql.SQLSyntaxErrorException: ORA-00933:SQLコマンドが正しく終了しませんでした

バインドを置換してSql Developerで問合せを実行すると、エラーなしで実行されます。どこでJavaコードが間違っていますか?

+0

はセミコロンを追加し、同じ間隔が(だと手動チェック;)SELECTステートメントの最後に、それが役立つかどうかを確認してください。 – mathguy

+2

@mathguy:いいえそれはひどいことになります:http://stackoverflow.com/q/10728377/330315 –

+0

残念ながら、間隔の値をそのようなパラメータとして渡すことはできません。 –

答えて

2

@a_horse_with_no_nameがコメント内で言ったように、間隔値をパラメータとして渡すことはできません。その形式はan interval literalであり、リテラル部分にはバインド変数を使用できません。

あなたが代わりにthe to_dsinterval() functionを使用するようにクエリを変更することができます。SQL * Plusを/ SQL Developerのバインド変数と

SELECT col FROM table WHERE 
last_updated > SYS_EXTRACT_UTC(systimestamp) - TO_DSINTERVAL(?) 

クイックデモ:

var val varchar2(30); 
exec :val := '0 00:01:30.0'; 

提供するために、CTEを持つクエリと同等のものをダミーデータ:

with t(last_updated, col) as (select systimestamp, 1 from dual) 
SELECT col FROM t WHERE 
last_updated > SYS_EXTRACT_UTC(systimestamp) - INTERVAL :val DAY TO SECOND(1); 

SQL Error: ORA-00933: SQL command not properly ended 

代わりに関数:

with t(last_updated, col) as (select systimestamp, 1 from dual) 
SELECT col FROM t WHERE 
last_updated > SYS_EXTRACT_UTC(systimestamp) - TO_DSINTERVAL(:val); 

     COL 
---------- 
     1 
3

問題はINTERVAL '0 00:01:30.0' DAY TO SECOND(1)がデータ型INTERVALのリテラルであるということです。したがって、その内部に位置パラメータを使用することはできません。

変換関数NUMTOYMINTERVALまたはNUMTODSINTERVALのいずれかを使用する必要があります。プリペアドステートメントのため

改正SQLは

SELECT col FROM table WHERE 
last_updated > SYS_EXTRACT_UTC(systimestamp) - NUMTODSINTERVAL(?,'SECOND') 

だろうとパラメータは、アレックスは自分自身を述べたように

stmt.setInt(1, 90); 

編集として設定する必要があります。もう一つの方法

SELECT col FROM table WHERE 
last_updated > SYS_EXTRACT_UTC(systimestamp) - TO_DSINTERVAL(?) 

とパラメータが文字列として設定することができ

stmt.setString("0 00:01:30.0"); 

それは

select NUMTODSINTERVAL(90,'SECOND') as "NUMTODSINTERVAL", 
     INTERVAL '0 00:01:30.0' DAY TO SECOND(1) as "INTERVAL", 
     TO_DSINTERVAL('0 00:01:30.0') as "TO_DSINTERVAL" 
from dual 

出力

NUMTODSINTERVAL  INTERVAL   TO_DSINTERVAL  
------------------- ------------------- ------------------- 
+00 00:01:30.000000 +00 00:01:30.000000 +00 00:01:30.000000 
+0

しかし、間隔文字列を数値に変換する必要があります。既存の文字列の値を直接取る 'to_dsinterval()'を使わないのはなぜですか? –

+0

@AlexPooleできます。それはあなたのコードで間隔がどのように利用できるかによって異なります。あまり一般的ではない文字列表現が見つかりました。 ;-)あなたの例を私の答えに加えました。 – SubOptimal

関連する問題