A SQL query comparing timestamps works in MySQL, but fails when using an H2 database.
As an example, this is the query that produces the exception:
SELECT * FROM table WHERE time >= '2019-02-01T10:59:12.632Z' AND time <= '2019-04-12T10:59:12.632Z'
The query is created dynamically using Java code, and the timestamps above are of type java.time.Instant.
I have even tried using other types of date/time objects, with the same outcome.
This query executes fine using MySQL, but throws the following error using an H2 DB:
org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement
"SELECT * FROM table WHERE time>= 2019-04-10T13[*]:31:19.498Z AND time <= 2019-04-07T13:31:19.498Z";
SQL statement:
SELECT * FROM table WHERE time >= 2019-04-10T13:31:19.498Z AND time<= 2019-04-07T13:31:19.498Z
I find it puzzling that using colon-separated timestamps cause this issue, especially since the H2 docs use similar timestamps
try converting date string properly
SELECT * FROM table WHERE time >= str_to_date('2019-02-01 10:59:12.632 ', '%Y-%m-%d %T.%f')
AND time <= str_to_date( '2019-04-12 10:59:12.632 ' , '%Y-%m-%d %T.%f')
I am using Spring Boot's JdbcTemplate and creating my queries as follows:
jdbcTemplate.query("SELECT * FROM table WHERE time >= " + startTime + " AND " + " time <= " + endTime, (rs, i) -> Accessor.readFromResultSet(rs));
with the date Strings passed in as Instant objects.
The solution, thanks to #OleV.V's comment, was to pass the date objects in as an Object argument:
jdbcTemplate.query("SELECT * FROM table WHERE time >= ? AND time <= ?", new Object[]{startTime, endTime}, (rs, i) -> Accessor.readFromResultSet(rs));
Related
I have this db table in an H2 database called "mytable" and two of the fields have the type "TIMESTAMP".
I have writen the following query in order to update the table:
UPDATE mytable
SET START_TIME_ = "2018-01-01 01:01:01" , END_TIME_ = "2020-01-01 01:01:01";
I was wondering how could I modify my query so that it generates at the START_TIME_ and END_TIME_ fields random dates between 2018-01-01 01:01:01 and 2020-01-01 01:01:01. As the H2 timestamp is not a UNIX timestamp I am unsure how to go about it. I appreciate any help you can provide.
In H2 1.4.200 you can use
UPDATE mytable SET
START_TIME_ = #T := TIMESTAMP '2018-01-01 01:01:01'
+ RAND() * INTERVAL '730 00:00:00' DAY TO SECOND,
END_TIME_ = #T + (TIMESTAMP '2020-01-01 01:01:01' - #T) * RAND();
INTERVAL '730 00:00:00' DAY TO SECOND can be replaced with the subtraction operation between high and low bounds (TIMESTAMP '2020-01-01 01:01:01' - TIMESTAMP '2018-01-01 01:01:01').
Note that distribution of START_TIME_ is linear here, but distribution of END_TIME_ is not. If such distribution doesn't satisfy your needs, you need to use some more complex expressions, but you can use the same datetime arithmetic operations in them.
Please also note that inline variable assignment syntax uses the := operator and not the = operator.
My code is performing the following update at a given time in my mysql database:
" UPDATE client_registration " +
" SET registration_date = NOW() " +
" WHERE cycle <= str_to_date(\"" + now + "\",'%d/%m/%Y %H:%i') ";
However I have a unit test that tries to perform this update on the HSQL database and I receive the following error message: user lacks privilege or object not found: STR_TO_DATE.
Some way to execute the condition WHERE cycle_start <= str_to_date(\"" + now + "\",'%d/%m/%Y %H:%i') for the mysql database and the hsql database?
You have to re-write your query for HSQL:
" UPDATE client_registration " +
" SET registration_date = NOW() " +
" WHERE cycle <= current_timestamp";
How to do "select current_timestamp" in hsqldb?
If you want to run the exact same query on both MySQL and HSQLDB, you need to create the STR_TO_DATE function on HSQLDB. You also need to use the single-quote character in your query: str_to_date('" + now + "','%d/%m/%Y %H:%i') (this quoting follows the SQL Standard).
It is easier if you use the SQL Standard format 'YYYY-MM-DD hh:mm:ss' (e.g '2020-07-21 14:30:00') for your 'now' variable and the format string you use with MySQL. In this case the HSQLDB function is simply created as:
CREATE FUNCTION STR_TO_DATE(STR VARCHAR(30), FORMAT VARCHAR(40) )
RETURNS TIMESTAMP
RETURN CAST(STR AS TIMESTAMP);
Execute the CREATE FUNCTION statement once when you connect to the database and you can use it in all your queries and upade statements.
I would like to get records that have date_time column is in a week from now, in a month from now
I have a query like this
public interface BookingRepository extends JpaRepository<Booking, Long> {
#Query("SELECT b " +
"FROM BOOKING b " +
"WHERE b.date_time < NOW() + INTERVAL 7 DAY and b.date_time > NOW()")
List<Booking> getListBooking();
}
In MySQL, NOW() + INTERVAL 7 DAY is working but in JPA #Query, I don't know which function is correspond to it.
In this situation, I have to use dynamic query instead of native query. So I'd like to use dynamic query and face this problem.
Please help.
Thank you!
there is no date_add in JPA so you would have few options:
use native query https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#_native_queries
implement custom jpa function for date modifications
parametrize query
personally i would go with query parametrization as it is easier to test and maintain in the long-run.
Good day,
I have a db2 database, and I have a sql query as follow:
select * FROM SCORPORATEREGISTEREDACCOUNTS CRA WHERE cra.corporateRegisteredAccountId = 241
and cra.paymentDate >= '2017-07-07 00:00:00' and cra.paymentDate <= '2017-07-07 23:59:59';
And in my database, the row record having paymentDate = '2017-07-07 11:48:00'. This paymentDate column is set as TIMESTAMP for its data type.
When I run this query through command, or through dbVisualizer, I can get the result correctly.
However, When run this query through java code using Hibernate Query, I will have some weird result, which is getting null record for the first time, and have record on the second time and onward, and If I log out from my java web application, and log in again, same problem occur.
Here is my sample code that trigger by a search button:
StringBuilder sb = new StringBuilder( );
sb.append( " \\ my query here " );
Query query = getSession( ).createSQLQuery( sb.toString( ) );
return query.list();
In other word, I have to press the search button second time only can get the correct result.
And here is some of my test case:
If I change the row record paymentDate to '2017-07-07 00:00:00', then it wont have issue for searching.
If I change my sql query to search within 2 day instead of 1 day, then it wont have issue also.
where cra.paymentDate >= '2017-07-07 00:00:00' and cra.paymentDate <= '2017-07-07 23:59:59'
Or I change my code to call the query.list() 2 times (only return at second time):
query.list();
return query.list();
However, my solution is cast the column to date:
where date(cra.paymentDate) >= '2017-07-07 00:00:00' and date(cra.paymentDate) <= '2017-07-07 23:59:59'
My question is, how come the original query wont work for first time, and only work for second time. If think as logic, it should fulfill the search criteria and return me correct result. Is it a Hibernate Query bugs? Or there is other reason or something wrong with my code.
Kindly advise.
I have created a native query with interval. The query works fine when i hard code day in query:
#Query(value="select * from orders where created_date < clock_timestamp() - interval ' 5 days'",nativeQuery=true)
But when i provide data with #Param like this:
#Query(value="select * from orders where created_date < clock_timestamp() - interval :day 'days'",nativeQuery=true)
List<Order> getData(#Param("day") String day)
I got this error:
Caused by: org.postgresql.util.PSQLException: ERROR: syntax error at
or near "$1"
You can't provide a value for an interval like that. You need to multiple the parameter value with your interval base unit:
"select * from orders
where created_date < clock_timestamp() - (interval '1' day) * :days"
As you are dealing with days, you can simplify that to:
"select * from orders
where created_date < clock_timestamp() - :days"
Another option is the make_interval() function. You can pass multiple parameters for different units.
"select * from orders
where created_date < clock_timestamp() - make_interval(days => :days)"
The notation days => ... is a named parameter for a function call. If the variable represents hours, you could use make_interval(hours => ..)
One solution is provided in this entry Spring Boot Query annotation with nativeQuery doesn't work in Postgresql
Basically:
#Query(value="select * from orders where created_date < clock_timestamp() - ( :toTime )\\:\\:interval",nativeQuery=true)
'toTime' is a Param from your repository and could be days, hour, minute... etc(review interval doc in Postgres) #Param("toTime") String toTime