2013-01-24 15 views
6

私はOracleのクエリで間隔パラメータをパラメータ化しようとする問題が生じています:Springという名前のパラメータ:クエリでOracleの間隔をパラメータ化する方法はありますか。

select current_timestamp - interval :hours hour from dual 

私は一定の間隔でパラメータを交換する場合、それがうまく実行されます。

SQLで引用符付きおよび引用符付きのパラメーターを試してみました。

は、以下の最小限のスニペットを使用して図を参照してください:

public class Main { 
    private static String SQL_CONSTANT_INTERVAL = "select current_timestamp - interval '1' hour from dual"; 

    private static String SQL_PARAMETERIZED_INTERVAL_QUOTED = "select current_timestamp - interval ':hours' hour from dual"; 

    private static String SQL_PARAMETERIZED_INTERVAL_UNQUOTED = "select current_timestamp - interval :hours hour from dual"; 

    public static void main(String[] args) throws Exception { 
     Properties properties = new Properties(); 
     properties.load(Main.class.getClassLoader().getSystemResourceAsStream("db.properties")); 
     DataSource dataSource = BasicDataSourceFactory.createDataSource(properties); 

     NamedParameterJdbcTemplate npTemplate = new NamedParameterJdbcTemplate(dataSource); 

     Map<String, String> params = Collections.singletonMap("hours", "1"); 

     String[] queries = 
       new String[] { SQL_CONSTANT_INTERVAL, SQL_PARAMETERIZED_INTERVAL_QUOTED, SQL_PARAMETERIZED_INTERVAL_UNQUOTED }; 

     for (String q : queries) { 
      System.out.println("Executing " + q); 
      try { 
       System.out.println("Result = " + npTemplate.queryForObject(q, params, String.class)); 
      } catch (RuntimeException e) { 
       System.out.println("Error: " + e); 
      } 
      System.out.println(); 
     } 
    } 
} 

出力:

Executing select current_timestamp - interval '1' hour from dual 
Result = 2013-01-24 18:55:16.373 Europe/Moscow 

Executing select current_timestamp - interval ':hours' hour from dual 
24-Jan-2013 20:55:16 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 
INFO: Loading XML bean definitions from class path resource [org/springframework/jdbc/support/sql-error-codes.xml] 
24-Jan-2013 20:55:16 org.springframework.jdbc.support.SQLErrorCodesFactory <init> 
INFO: SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase] 
Error: org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [select current_timestamp - interval ':hours' hour from dual]; ORA-01867: the interval is invalid 
; nested exception is java.sql.SQLDataException: ORA-01867: the interval is invalid 


Executing select current_timestamp - interval :hours hour from dual 
Error: org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [select current_timestamp - interval ? hour from dual]; nested exception is java.sql.SQLSyntaxErrorException: ORA-00923: FROM keyword not found where expected 
+0

ソースコード:https://gist.github.com

NUMTODSINTERVAL(1, 'HOUR') 

が次にあなたがそうのようなあなたのJava SQLで整数リテラルを置き換えることができます/ 4632533 – vitaly

答えて

7

interval '1' hourは、Oracle literalです。そのため、バインドパラメータを使用して、その真ん中の'1'を置き換えることはできません。

代わりに、あなたはこれを使用することができます。

NUMTODSINTERVAL(?, 'HOUR') 
+0

チャームのように働いた、ありがとう。私はSpring(またはJDBC?)にリテラルの変数を代入する際に問題があることを理解していませんでした – vitaly

+2

実際にはOracleの制限です。 Spring/JDBC問合せ変数は、データベースが実行する実際の問合せでOracleバインド変数に変わり、Oracleリテラルの中間に何かを置き換えるためにバインド変数を使用することはできません。 – GriffeyDog