Im new to sql and im facing a problem with the below native query
public void saveOfflineBatchDetails(BigInteger user_id) {
em.createNativeQuery("INSERT INTO rst_offline_transaction_batch (created_date , user_id)" +
"VALUES('?1', ?2)")
.setParameter(1, new java.util.Date())
.setParameter(2, user_id)
.executeUpdate();
}
It doesn't pass the values to the database. the created date should be the today's date and time. Can anyone tell me whats wrong in this query.
Thanks a lot
You generally don't include the single quotes for parameterised queries. Try:
VALUES(?1, ?2)
(without the quotes around the ?1). Otherwise it's hard (for both readers and parsers) to tell whether you wanted parameter 1 or the literal value ?1 to be inserted.
You should also check the return value from executeUpdate() to see if it thinks it affected any rows. This will probably give you zero but it's worth checking anyway.
And, finally, I think dates require special handling as per:
setParameter(1, new java.util.Date(), TemporalType.DATE);
This is because the Java Date object is not a date at all but a timestamp - you need to ensure you select the correct temporal object type so that the right value is placed in the query.
So, in short, something like:
int affected = em.createNativeQuery(
"INSERT INTO rst_offline_transaction_batch (" +
" created_date," + // ?1
" user_id" + // ?2
") VALUES (?1,?2)"
)
.setParameter(1, new java.util.Date(), TemporalType.DATE)
.setParameter(2, user_id)
.executeUpdate();
// Check affected.
Related
I have a query to test two dates against two timestamp columns in the table if they overlap or not.
Query is working fine in the database client but when i added it in my java code it fails with an exception error.
I need to know how to format the && symbols in the query to be able to work.
SELECT count(*)
FROM attendance_jobs
WHERE tsrange( start_date, end_date) && tsrange(TIMESTAMP '2019-04-22', TIMESTAMP '2019-03-22 ')
Here is my java code:
long count = jdbi.withHandle(handle -> {
return handle.createQuery("select count(*) from attendance_jobs where tsrange(start_date, end_date) && tsrange(timestamp :start_date, timestamp :end_date)")
.bind("start_date", start_date)
.bind("end_date", end_date)
.mapTo(Long.class)
.findOnly();
});
The start_date and end_date data type is Timestamp.
org.jdbi.v3.core.statement.UnableToExecuteStatementException: org.postgresql.util.PSQLException: ERROR: syntax error at or near "$1"
This is just guesswork, but I think you should have a look at the usage of :start_date and :end_date again:
If start_date and end_date (java variables) are of type Timestamp you should remove the timestamp prefix to :start_date and :end_date in the query. As the documentation says, the java type Timestamp is supported by jdbi:
Out of the box, Jdbi supports the following types as SQL statement arguments:
* ...
* java.sql: Blob, Clob, Date, Time, and Timestamp
* ...
So my guess is that you have to use the query like this:
long count = jdbi.withHandle(handle -> {
return handle.createQuery("select count(*) from attendance_jobs where tsrange(start_date, end_date) && tsrange(:start_date, :end_date)")
.bind("start_date", start_date)
.bind("end_date", end_date)
.mapTo(Long.class)
.findOnly();
});
Also, but this may be personal taste, I recommend to use different spelling of bind variables and database columns. The latter with underscores (as you did), the other in camel case so it is less confusing if you use similar names. Also, it is uncommon to use underscores in java variables, so the code would look similar to this in my spelling:
Timestamp startDate = ...;
Timestamp endDate = ...;
String queryString = "select count(*) from attendance_jobs "
+ "where tsrange(start_date, end_date) && tsrange(:startDate, :endDate)";
long count = jdbi.withHandle(handle -> {
return handle.createQuery(queryString)
.bind("startDate", startDate)
.bind("endDate", endDate)
.mapTo(Long.class)
.findOnly();
});
I'm working on a small program that lists local train stops in a numbered list then asks for the user to type the number of the station that they wish to see the next arrival time for.
The problem I have is I don't think the MySQL query is correct to retrieve the arrival time. The list returns empty. Using jdbc previously, this query worked fine:
"SELECT arrival_time FROM stop_times WHERE stop_id = '"
+ myStation.getID()
+ "' AND arrival_time > time('now', 'localtime') ORDER BY arrival_time asc;";
And the current hibernate query:
public List<String> getArrivals() {
sessionFactoryBean.getCurrentSession().beginTransaction();
String sql = "SELECT arrival_time FROM stop_times WHERE stop_id = '"
+ myStation.getID()
+ "' AND arrival_time > time('now', 'localtime') ORDER BY arrival_time asc;";
Query query = sessionFactoryBean.getCurrentSession()
.createSQLQuery(sql)
.addEntity(Station.class);
List<String> arrivals = query.list();
sessionFactoryBean.getCurrentSession().getTransaction().commit();
return arrivals;
}
Called from this method and where I get IndexOutOfBoundsException:
public String getNextArrival(int user_input) {
getStationName(user_input);
List<String> arrivals1 = arrival.getArrivals();
System.out.println(arrivals1);
System.out.println(arrivals1.size());
String arrivalTime = arrivals1.get(user_input);
return convertTime(arrivalTime);
}
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0,
Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:653)
at java.util.ArrayList.get(ArrayList.java:429)
at com.moeller.code.Stops.getNextArrival(Stops.java:73)
Line 73 String arrivalTime = arrivals1.get(user_input);'
The DataBase is stored locally.
There are several problems with this.
First, the query does not use parameters, which means you will likely make this mistake elsewhere where it will be a danger. You have to pass on variables like this:
String sql = "SELECT arrival_time FROM stop_times WHERE stop_id = ?"
+ " AND arrival_time > time('now', 'localtime') ORDER BY arrival_time asc;";
Query query = sessionFactoryBean.getCurrentSession()
.createSQLQuery(sql)
.addEntity(Station.class);
query.setParameter(1, myStation.getID());
See the question mark? That is a positional parameter. You can also use named parameters.
String sql = "SELECT thing FROM table WHERE column1 LIKE :ptrn";
...
query.setParameter("ptrn", "%that%");
Notice how inside the query the parameter starts with :, but it does not when calling setParameter.
This way of safely inserting parameters is called using "Prepared Statements", or "Parameterized Queries". Find a quick tutorial on them, they are very important.
Secondly, in getNextArrival you forget to check if the list has that many elements.
if (arrivals1.size() <= user_input) {
return null;
}
Of course then you have to be careful when it returns a null to the function where it's used.
You are using a wrong method for the List.
when yo use List.get(param) param should be the position that you are looking for, no the userInput.
you need loop the list and compare each position of the list with the user input.
best Regards
In my java code, i am trying to perform insert operation but for some reasons i am getting SQLSyntaxErrorException . I am not getting the reason behind it though i tried. Below is my code.
Query nativeQuery = em.createNativeQuery(
"insert into TABLE_DIMENSION (DIMESNION_ID, DIMENSION_CODE, TABLE_CODE, TABLE_IND, CREATE_TIME, "
+ "CREATE_PLACE, CHG_DT, CHG_WARDANT) "
+ " (select TABLE_DIMENSION_SEQ.nextval, d.name,:dimensionCode, 0, :time, :place, :date, :wardant from table_master d where d.name in (:table_dimension_ids)) ");
nativeQuery.setParameter("date", new Date());
nativeQuery.setParameter("table_dimension_ids", tableDimensionList);
nativeQuery.setParameter("dimensionCode", dimensionCode);
nativeQuery.setParameter("wardant", wardant);
number = nativeQuery.executeUpdate();
Please guide.
You told your query that you will use 6 parameters but you set just 4 parameters, you are missing to put :place and :time in the parameters like the others, so you have to use :
nativeQuery.setParameter("place", place);
nativeQuery.setParameter("time", time);
before you execute your query, else you have to remove it from your query
You should skip ():
insert into TABLE_DIMENSION
(DIMESNION_ID, DIMENSION_CODE, TABLE_CODE, TABLE_IND
, CREATE_TIME, CREATE_PLACE, CHG_DT, CHG_WARDANT)
select TABLE_DIMENSION_SEQ.nextval, d.name,:dimensionCode, 0
, :time, :place, :date, :wardant
from table_master d
where d.name in (:table_dimension_ids)
I have the following
DateFormat dformat = new SimpleDateFormat("yyyy-M-d");
dformat.setLenient(false);
Date cin = dformat.parse(cinDate);
and the sql function
create or replace function search(_checkIn date, _checkOut date) returns setof Bookings as $$
declare
r Bookings;
begin
for r in
select * from Bookings
loop
if ((_checkIn between r.checkIn and r.checkOut) or (_checkOut between r.checkIn and r.checkOut)) then
return next r;
end if;
end loop;
return;
end;
$$ language plpgsql;
The date format for the postgresql is standard (default)
create table Bookings (
id serial,
status bookingStatus not null,
pricePaid money not null,
firstName text,
lastName text,
address text,
creditCard text,
checkOut date not null,
checkIn date not null,
room integer not null,
extraBed boolean not null default false,
foreign key (room) references Rooms(id),
primary key (id)
);
and I'm trying to parse a date into the function so it can return a table for me, I seem to run into the issue of date formatting (which is why I think I'm getting this error)
org.postgresql.util.PSQLException: ERROR: syntax error at or near "Feb"
So I was wondering how would I fix this problem, I don't know how to format the date properly
EDIT:
I'm calling the query like this
try {
String searchQuery = "SELECT * FROM Rooms r where r.id not in (select * from search(" + cin +", " + cout +"))";
PreparedStatement ps = conn.prepareStatement(searchQuery);
rs = ps.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
}
so I think the error comes in because the way I format the date is wrong and postgres won't read it
It sounds like you're passing the argument by concatenating them directly into the string. This is a very bad idea, since it can lead to SQL injections. Always use PreparedStatements with the ? place-holders to pass parameters, never pass them directly by concatening them directly into the query string (more so, you'd need the ' delimiters around).
You could have something like:
PreparedStatement stmt
= con.prepareStatement("SELECT id FROM Bookings WHERE checkIn=?")
stmt.setDate(1, new java.sql.Date(cin.getTime()));
// ? parameters are indexed from 1
ResultSet results = stmt.executeQuery();
Alternatively, PostgreSQL internal date conversion is usually fairly good and flexible. You could cast the string parameter to a date with PostgreSQL:
PreparedStatement stmt
= con.prepareStatement("SELECT id FROM Bookings WHERE checkIn=CAST(? AS DATE)");
stmt.setString(1, cinDate);
ResultSet results = stmt.executeQuery();
This is flexible, but might not lead to the exact result you need depending on the date format (you can check the PostgreSQL manual for details on date conversion formats). The input format you're using should work just fine, though (Try SELECT CAST('2012-05-01' AS DATE) directly in PostgreSQL, for example, this will return a correct PostgreSQL date.)
Note that when using new java.sql.Date(cin.getTime()), you're likely to run into time zone issues. You could use java.sql.Date.valueOf(...) too.
To clarify, following your edit:
This will not work, since the dates would be part of the SQL syntax itself, not strings or dates: "SELECT * FROM Rooms r where r.id not in (select * from search(" + cin +", " + cout +"))"
You'd at least need to use ' quotes: "SELECT * FROM Rooms r where r.id not in (select * from search("' + cin +"', '" + cout +"'))". Here, to a degree, you could expect the parameters to be formatted properly, but don't do it. In addition, would would still have to cast the string using CAST('...' AS DATE) or '...'::DATE.
The simplest way would certainly be:
String searchQuery = "SELECT * FROM Rooms r where r.id not in (select SOMETHING from search(CAST(? AS DATE), CAST(? AS DATE)))";
PreparedStatement ps = conn.prepareStatement(searchQuery);
ps.setString(1, cinDate);
ps.setString(2, coutDate);
(As a_horse_with_no_name pointed out in a comment, the general query wouldn't work anyway because of your inner select.)
You already have advice concerning prepared statements and proper format.
You can also largely simplify your PostgreSQL function:
CREATE OR REPLACE FUNCTION search(_checkin date, _checkout date)
RETURNS SETOF bookings AS
$BODY$
BEGIN
RETURN QUERY
SELECT *
FROM bookings
WHERE _checkin BETWEEN checkin AND checkout
OR _checkiut BETWEEN checkin AND checkout;
END;
$BODY$ language plpgsql;
Or even:
CREATE OR REPLACE FUNCTION search(_checkin date, _checkout date)
RETURNS SETOF bookings AS
$BODY$
SELECT *
FROM bookings
WHERE _checkin BETWEEN checkin AND checkout
OR _checkiut BETWEEN checkin AND checkout;
$BODY$ language sql;
Rewrite the LOOP plus conditions to a plain SQL statement which is much faster.
Return from a plpgsql function with RETURN QUERY - simpler and faster than looping.
Or use a plain sql function.
Either variant has its advantages.
No point in using mixed case identifiers without double quoting. Use all lower case instead.
According to this page, the standard format for date/time strings in SQL is:
YYYY-MM-DD HH:MM:SS
And of course for dates you can use
YYYY-MM-DD
PostgreSQL accepts other formats (see here for some details) but there's no reason not to stick to the standard.
However, since you are getting a syntax error it sounds like you are injecting the date strings into your SQL statement without the proper quoting/escaping. Double-check that you are properly escaping your input.
I have a table on my jsp page that will have a column populated by a database column with type CLOB. I am running into some trouble doing this, and have seen other questions asked about this, but the answers have not worked for me. Here is my statement where comments is a CLOB.
stmt = conn.prepareStatement("SELECT DISTINCT restriction, person, start_date, end_date, comments "
+ " FROM restrictions WHERE person = ? "
+ " AND (start_date BETWEEN TO_DATE (? , 'yyyy/mm/dd') AND TO_DATE (? , 'yyyy/mm/dd') "
+ " OR start_date < TO_DATE (? , 'yyyy/mm/dd') AND end_date IS NULL) " );
stmt.setString(1, Id);
stmt.setString(2, StartRest);
stmt.setString(3, EndRest);
stmt.setString(4, EndRest);
result = stmt.executeQuery();
And then I will have the columns in a while loop:
while (result.next()) {
restrictions = StringUtils.defaultString(result.getString("str_restriction"));
.......
// here is where I would get my Clob data from the query.
So, basically, I was wondering if there is a way to translate the CLOB in the query, or even in the java code, so it would be usable in my page.
The problem comes from the distint clause of the query, which can't be applied to a CLOB.
Check if the distinct keyword is really needed. Or maybe you could rewrite your query as
select restriction, person, start_date, end_date, comments from restrictions
where id in (select distinct id from restrictions where <original where clause>)
PS: next time, include the error message and your database in the question. I've been able to find the problem with a simple google search on "ora-00932 clob".