How to resolve MySQLSyntaxErrorException in JDBC preparedStatement [duplicate] - java

This question already has answers here:
Variable column names using prepared statements
(7 answers)
Closed 5 years ago.
I have a query that throws a com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException and I can't figure out why. I am using xampp and when I try the same query directly, it works fine. I also have a whole bunch of other methods that use very similar queries that all work.
The problem seems to be with updating the date, I noticed in the error message that java puts ' ' around the date, which makes it a string and is probably the reason for the error. However I'm not sure how to fix this to insert the date as a date.
Here's the code:
public void update(int userId, String date, String column, String value){
try {
// convert date from String to Date
DateTime dt = DateTime.parse(date);
java.sql.Date sqlDate = new java.sql.Date(dt.getMillis());
// create prepared statement
conn = DriverManager.getConnection("jdbc:mysql://localhost/db","root", "");
String query = "UPDATE expenses_income SET ? = ? WHERE userId = ? AND date = CAST(? AS DATETIME);";
PreparedStatement preparedStmt = conn.prepareStatement(query);
preparedStmt.setString(1, column);
preparedStmt.setString(2, value);
preparedStmt.setInt(3, userId);
preparedStmt.setDate(4, sqlDate);
preparedStmt.executeUpdate();
conn.close();
} catch (Exception e) {
System.err.println("MySQL exception: " + e);
}
}
And the error message:
MySQL exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''comment' = '123' WHERE userId = 1 AND date = CAST('2018-01-06' AS DATETIME)' at line 1
I also tried the query without casting as datetime:
String query = "UPDATE expenses_income SET ? = ? WHERE userId = ? AND date = ?;";
But I get the same error.
I then tried to use java.util.Date instead of Joda DateTime, but it doesn't help. Any ideas?
Thanks!

.. right syntax to use near ''comment' = '123'
You are getting exception because column name parameterization, which is not correct.
UPDATE expenses_income SET ? = ?
It should be
UPDATE expenses_income SET column_name = ?
I also noticed a semicolon ; at the end of the SQL, which should be removed and you don't need to cast Date explicitly. It should be just
UPDATE expenses_income SET column_name = ? WHERE userId = ? AND date = ?
Also, you shouldn't name column name like date, it should be last_updated or something meaningful.

Related

java.sql.Timestamp to Date Conversion in Oracle SQL

I have run into this weird Timestamp to Date Conversion issue in Oracle SQL.
Here is the SQL statement:
String INSERT_SQL = String.format("INSERT INTO AUDIT_TASK (%s, %s, %s, %s) VALUES (AUDIT_TASK_SEQ.nextval,?,?,?)",ID,CLASS_NAME,TASK_STEP_TIMESTAMP,OPERATOR);
java.util.Calendar utcCalendarInstance = Calendar.getInstance(TimeZone .getTimeZone("UTC"));
java.util.Calendar cal = Calendar.getInstance();
final PreparedStatement stmt = con.prepareStatement(INSERT_SQL);
stmt.setString(1, audit.getClassName().getValue());
// Save the timestamp in UTC
stmt.setTimestamp(2,new Timestamp(cal.getTimeInMillis()), utcCalendarInstance);
When I execute this statement, while most of the times the creation_date and task_step_timestamp dates are same, but sometimes I get the task_step_timestamp generated with some bogus dates- like '25-APR-0000' or '00-Jan-0001' etc.
ID | Creation_date | Task_step_timestamp
1 |27-APR-2018 17:58:53| 25-APR-0000 09:00:45
2 |27-APR-2018 18:06:25| 00-Jan-0001 09:18:25
The data type of task_step_timestamp column in Oracle DB is 'DATE'.
Can some one suggest the cause of this inconsistent conversion of timestamp to date?
I don't understand why you are using String#format here. Just use a regular insert which mentions explicit columns:
String INSERT_SQL = "INSERT INTO AUDIT_TASK (ID, ERROR_MESSAGE, TASK_STEP_TIMESTAMP, OPERATOR) ";
INSERT_SQL += "VALUES (AUDIT_TASK_SEQ.nextval, ?, ?, ?)";
PreparedStatement stmt = con.prepareStatement(INSERT_SQL);
Then bind your values:
stmt.setString(1, audit.getErrorMessage() != null ? audit.getErrorMessage().getValue() : null);
stmt.setTimestamp(2, new Timestamp(cal.getTimeInMillis()), utcCalendarInstance);
stmt.setString(3, audit.getClassName().getValue());
Note carefully that the placeholders, in order from left to right, are for the error message, task step timestamp, and operator. Your original code appears to be binding the parameters out of order. By using an insert statement which explicitly mentions the columns, you may avoid this problem.
Edit:
It also doesn't make sense to me why you are worrying about time zones for your timestamp. Just get the numbers of milliseconds since the epoch, and then let the database store that as UTC:
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
stmt.setTimestamp(2, timestamp);

Why I obtain this error on a date field when I try to perform this query on SQL Server?

I am finding some difficulties trying to perform this SQL query (on Microsoft SQL Server) into a Java appliction.
So I have this method that perform a simple select query:
public void insertOrUpdate_TIRConsolidatoPolizza(QS_TirPolizza qsTir) throws Exception {
try{
log.debug("PucManager.insertOrUpdate_TIRConsolidatoPolizza");
// Reperisce i parametri della query dal parametro passato:
String numeroPolizza = qsTir.getPolizzaid().toString();
Long annoRiferimento = qsTir.getAnnoRiferimento();
String dataRiferimentoNav = qsTir.getDataRiferimentoNav() != null ? "'"+qsTir.getDataRiferimentoNav()+"'" : null;
String timestamp = qsTir.getTimestamp() != null ? "'"+qsTir.getTimestamp()+"'" : null;
String sql = "select * from TirConsolidatoPolizza" +
" where Polizzaid = " + numeroPolizza +
" and DataRiferimentoNav = " + dataRiferimentoNav;
log.debug("Query: " + sql);
PreparedStatement ps = con.prepareStatement( sql );
log.debug("Eseguo Query");
ResultSet rs = ps.executeQuery();
...................................................
...................................................
DO SOMETHING ELSE
...................................................
...................................................
}
The String sql variable value is (I see it printing it by log.debug()):
select * from TirConsolidatoPolizza where Polizzaid = 9999999999 and DataRiferimentoNav = 'Thu Jun 23 10:36:43 CEST 2016'
This query can't work because it seems that I have a problem with the DataRiferimentoNav value.
I obtain the following error message:
10:42:41 [SELECT - 0 row(s), 0.000 secs] [Error Code: 241, SQL State: S0001] Conversion failed when converting date and/or time from character string.
The DataRiferimentoNav (it is a datetime on the db table) value is taken from the qsTir.getDataRiferimentoNav() object field that is a String (I can't change it) representing a date and that was setted in this way elsewhere in my code:
qsTir.setDataRiferimentoNav(new Date().toString());
So, what is wrong? What am I missing? How can I solve this issue and correctly perform my query?
You need to proper format the date to be understood by the database:
Format formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String formatted = formatter.format(qsTir.getDataRiferimentoNav());
Ideally, you should avoid concatenating SQL as this can lead you to SQL injection vulnerabilities. Try to use parameterized queries to achieve your goal.

Saving a Date to MySQL database [duplicate]

Can anyone help me with a sample JSP code to store date in a MySql database through JDBC?
When I try to execute the code given below, I get the following exception:
com.mysql.jdbc.MysqlDataTruncation: Data truncation: Incorrect datetime value: '' for column 'date' at row 1
How to overcome this problem? Following is my code:
Connection con = null;
String StaffName = request.getParameter("StaffName");
// String subcode = request.getParameter("subcode");
String hourId = request.getParameter("hourId");
if (hourId == null)
hourId = "";
String day = request.getParameter("day");
if (day == null)
day = "";
String date = request.getParameter("date");
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/StaffAllocation", "root", "success");
// PreparedStatement stat = con.PrepareStatement();
String updateString = "INSERT INTO tblstaffallocation (StaffName,hourId,daysId,date) VALUES (?,?,?,?)";
PreparedStatement preparedStatement = con.prepareStatement(updateString);
preparedStatement.setString(1, StaffName);
preparedStatement.setInt(2, 0);
preparedStatement.setInt(3, 0);
preparedStatement.setString(4, date);
} catch (Exception e) {
out.print(e);
}
To set date to prepared statement you need change type of value:
String date = request.getParameter("date");
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); // your template here
java.util.Date dateStr = formatter.parse(date);
java.sql.Date dateDB = new java.sql.Date(dateStr.getTime());
now convert String date to java.sql.Date and use another method:
preparedStatement.setDate(4,dateDB);
I had a similar error. It turns out I just needed to update the jar version for mysql-connector-java (using maven)
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>...</version>
</dependency>
Try reformating the date
String date = new SimpleDateFormat("yyyy-MM-dd")
.format(new Date(request.getParameter("date")));
and then insert into the database.
Note that request.getParameter("date") should be in format 11/20/2013 for this to work or you can use a similar way to achieve.
Make sure that the Date value that you are trying to insert into the table is exactly in the format defined in the date column of your table.
I know this is an old thread, but none of these solutions solved the problem for me. What worked for me was to upgrade hibernate to version 5.2.10.Final (see this SO post).
Running Spring Boot and Spring Data JPA 1.5.4.RELEASE and hibernate 5.2.10.Final.
If someone will have similar error for entity field with Data type annotated as #Temporal, the solution for me was to replace annotation value TemporalType.TIMESTAMP by TemporalType.TIME:
#Temporal(TemporalType.TIMESTAMP)
private Date dateField;
should be like this:
#Temporal(TemporalType.TIME)
private Date dateField;
Another way to resolve this problem without any changes in code (at least for me) was to run application on higher Tomcat version, hope it will help.
Accepted answer only handles date, not datetime. Anyways...
My problem was it didn't accept really old datetime's. I generated date in .net environment, where default date was "1900-01-01 01:01:01". I had to change date to somthing later in time... Ooops.
My error message:
com.mysql.jdbc.MysqlDataTruncation: Data truncation: Incorrect datetime value: '1900-01-01 01:01:01' for column 'added' at row 1

JDBC delete rows in db with specific timestamp

I have a database in which I am saving messages with tiemstamps. I have table created with this code:
CREATE TABLE messages (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
msgid VARCHAR(64) UNIQUE,
payload TEXT,
sender VARCHAR(255),
cur_timestamp TIMESTAMP(3)
);
This all works perfectly. However, now I am trying to delete some rows with timestamp older than some specified by user. This is done in Java part of my system like this:
// get current timestamp
Date date = new Date();
// timestamp has to be in the same format as in database
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd h:mm:ss.SSS");
String formattedDate = sdf.format(date);
System.out.println("Current time: " + formattedDate);
// subtract desired time
if (msgOld.equals("hour")) {
date.setTime(date.getTime() - ONE_HOUR_MILLISCONDS);
formattedDate = sdf.format(date);
} else if (msgOld.equals("day")) {
date.setTime(date.getTime() - ONE_DAY_MILLISCONDS);
formattedDate = sdf.format(date);
}
This, too, works fine - the constants look like this: final long ONE_HOUR_MILLISCONDS = 60 * 60 * 1000;
The only problem is that I dont know how to write the query in JDBC. I tried doing this:
// prepare query
String query;
if (msgOld.equals("all")) {
query = "TRUNCATE TABLE messages";
} else {
query = "DELETE FROM messages WHERE cur_timestamp < " + date + ";";
}
but it says I have an error in my SQL statement (the second one, the one with TRUNCATE works fine). I tried putting formattedDate instead of date in the statement, too.
Whats wrong with it (probably something really simple - maybe difference between java.util.Date and SQL timestamp...)? Thanks for any tips!
EDIT: Thanks for all responses... I have rewritten the code so it uses prepared statement like this:
// prepare query
String query;
PreparedStatement pstmt = null;
try {
if (msgOld.equals("all")) {
query = "TRUNCATE TABLE messages";
pstmt=conn.prepareStatement(query);
} else {
query = "DELETE FROM messages WHERE cur_timestamp < ?;";
pstmt = conn.prepareStatement(query);
pstmt.setString(1, timestamp.toString());
}
} catch (Exception e) {
e.printStackTrace();
}
try {
pstmt.execute();
System.out.println("Successfully deleted messages.");
pstmt.close();
} catch (Exception e) {
System.out.println("Error with db query.");
e.printStackTrace();
}
but I am still getting SQL exception (even if I convert date to timestamp and like this Timestamp timestamp = new Timestamp(date.getTime()); and use it in the satement)
You cannot just concatenate java.util.Date objects into query string. That's wrong.
Better use PreparedStatement for this kind of things.
Take a look at this tutorial for example
exactly as #Funtik said preparedStatement could be used.
See this link here
it would not exactly sove your problem but you will get a clear idea.

MySQL syntax error using Java in Eclipse

I have the following prepared statement for sql in Java :
com.mysql.jdbc.JDBC4PreparedStatement#6e56103e:
INSERT INTO `game` (Id , GameStart ,Name, Lenght, MapVersion, Mode)VALUES(2502591,'2000-03-02 02:02:02','5x5 aptb wdw','00:55:48','DotA v6.75b.w3x','aptb ')ON DUPLICATE KEY UPDATE `Id`=VALUES(Id),`GameStart` = VALUES(GameStart),`Name`=VALUES(Name),`Lenght`=VALUES(Lenght),`MapVersion`=VALUES(MapVersion),`Mode`=VALUES(Mode).
When I execute it in Eclipse I get the following error:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?,?,?,?,?,?)ON DUPLICATE KEY UPDATE `Id`=VALUES(Id),`GameStart` = VALUES(GameSta' at line 1.
But at the same time when I execute the same query in SQLyog I don't get an error. Rows are updated. What can be a problem? Thanks in advance
Code:
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/dota","root","root");
PreparedStatement updateGame = null;
String updatingGame = "INSERT INTO `game` (Id , GameStart ,Name, Lenght, MapVersion, Mode)" +
"VALUES(?,?,?,?,?,?)" +
"ON DUPLICATE KEY UPDATE " +
"`Id`=VALUES(Id),"+
"`GameStart` = VALUES(GameStart)," +
"`Name`=VALUES(Name)," +
"`Lenght`=VALUES(Lenght)," +
"`MapVersion`=VALUES(MapVersion)," +
"`Mode`=VALUES(Mode)";
con.setAutoCommit(false);
updateGame=con.prepareStatement(updatingGame);
updateGame.setInt(1, game.Id);
Timestamp timestamp = new Timestamp(100,2,2,2,2,2,2);
updateGame.setTimestamp(2,timestamp);
updateGame.setString(3, game.GameName);
updateGame.setTime(4, (Time) game.Time);
updateGame.setString(5, game.MapVersion);
updateGame.setString(6, game.Mode);
updateGame.executeUpdate(updatingGame);
And on:
updateGame.executeUpdate(updatingGame);
I get an error
Firstly if you are using a preparedStatement you have to do it this way
String query="Insert into tablename (col1, col2) values(?,?)";
PreparedStatement stmnt = //get the statement
stmnt.setString(1, "col1val");
stmnt.setString(2, "col2val");
You are inserting a duplicate value on the primary key.
Follow the #chaitanya10 suggestion, use PreparedStatement
How is your knowledge about Object Orientation? As I can see you aren't using correctly encapsulation.
Found my mistake. I should use only executeUpdate() instead of executeUpdate(updatingGame) ;, because if I use it with parameter, I will overwrite values whiten by
updateGame.setInt(1, game.Id);
Timestamp timestamp = new Timestamp(100,2,2,2,2,2,2);
updateGame.setTimestamp(2,timestamp);
updateGame.setString(3, game.GameName);
updateGame.setTime(4, (Time) game.Time);
updateGame.setString(5, game.MapVersion);
updateGame.setString(6, game.Mode);

Categories

Resources