I am using Spring JdbcDaoSupport in my DAO and trying to update the records using the following query.
String callersUpdateQuery = "update W67U999S a set pcrdattim= ? where exists (select b.CRDATTIM, b.RECORDCD, b.CRNODE, b.UNITCD, b.WRKTYPE from W03U999S b where a.PCRDATTIM = ? and a.CCRDATTIM = b.CRDATTIM and a.CRECORDCD = b.RECORDCD and a.CCRNODE = b.CRNODE and a.PRECORDCD = 'F' and a.PCRNODE = '01' and b.WRKTYPE = 'CALLER' and b.UNITCD=? and a.crecordcd='T')";
The following is the code that should update the table:
int updatedRowsCount =getJdbcTemplate().update(callersUpdateQuery, new Object[]{newFolderCrdattim, crdattim, businessAreaName});
But getJdbcTemplate().update() is not updating the required rows and returning the updated rows count as zero. Weirdly, the same sql query when I execute at the database end, the records are getting updated. Can anyone guess what's wrong with the code or query?
The log messages are also showing correct values, but somehow the query is not updating the database:
21:04:01,288 DEBUG [org.springframework.jdbc.core.JdbcTemplate.execute] Executing prepared SQL statement [update W67U999S a set pcrdattim= ? where exists (select b.CRDATTIM, b.RECORDCD, b.CRNODE, b.UNITCD, b.WRKTYPE from W03U999S b where a.PCRDATTIM = ? and a.CCRDATTIM = b.CRDATTIM and a.CRECORDCD = b.RECORDCD and a.CCRNODE = b.CRNODE and a.PRECORDCD = 'F' and a.PCRNODE = '01' and b.WRKTYPE = 'CALLER' and b.UNITCD=? and a.crecordcd='T')]
21:04:01,288 DEBUG [org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection] Fetching JDBC Connection from DataSource
21:04:01,288 DEBUG [org.springframework.jdbc.datasource.DriverManagerDataSource.getConnectionFromDriver] Creating new JDBC DriverManager Connection to [jdbc:oracle:thin:#10.193.244.225:1521:AWD]
21:04:03,865 TRACE [org.springframework.jdbc.core.StatementCreatorUtils.setParameterValueInternal] Setting SQL statement parameter value: column index 1, parameter value [2017-08-09-10.33.10.168480], value class [java.lang.String], SQL type unknown
21:04:03,865 TRACE [org.springframework.jdbc.core.StatementCreatorUtils.setParameterValueInternal] Setting SQL statement parameter value: column index 2, parameter value [2017-07-20-04.22.20.893340], value class [java.lang.String], SQL type unknown
21:04:03,865 TRACE [org.springframework.jdbc.core.StatementCreatorUtils.setParameterValueInternal] Setting SQL statement parameter value: column index 3, parameter value [CS2XAA], value class [java.lang.String], SQL type unknown
21:04:04,115 DEBUG [org.springframework.jdbc.core.JdbcTemplate.doInPreparedStatement] SQL update affected 0 rows
21:04:04,131 DEBUG [org.springframework.jdbc.datasource.DataSourceUtils.doReleaseConnection] Returning JDBC Connection to DataSource
Oracle CHAR type is the culprit here. The columns that I want to update are of type CHAR. That's causing the issue. This link helped me in figuring out the solution:
Oracle JDBC and Oracle CHAR data type
Related
This question already has answers here:
When to use single quotes, double quotes, and backticks in MySQL
(13 answers)
Having a Column name as Input Parameter of a PreparedStatement
(1 answer)
Closed 1 year ago.
I am writing a student management app and have created a function to update student data-
public static void updateStudent(int id, int input) throws SQLException {
Scanner sc = new Scanner(System.in); //Scanner object
Connection connection = ConnectionSetup.CreateConnection(); //Setting up connection
String updateStatement = "UPDATE student_details SET ? = ? WHERE 's_id' = ?;"; //Initializing query
PreparedStatement pstmt = connection.prepareStatement(updateStatement);
System.out.println("Enter new name: ");
String newName = sc.nextLine();
pstmt.setString(1,"s_name"); //sets first ? to the columnname
pstmt.setString(2,newName); //sets the second ? to new name
pstmt.setString(3, String.valueOf(id)); //sets the third ? to the student ID
pstmt.execute(); //executes the query
All the other CRUD functions work fine, but this one throws the following error after inputting all the info-
Exception in thread "main" java.sql.SQLSyntaxErrorException: 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 ''s_name' = 'Prateek' WHERE 's_id' = '6'' at line 1
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953)
at com.mysql.cj.jdbc.ClientPreparedStatement.execute(ClientPreparedStatement.java:371)
at com.Student.manage.StudentFunc.updateStudent(StudentFunc.java:76)
at Start.main(Start.java:58)
I tried printing the finalized query and it has correct syntax and works in the MySQL Console-
SQL Query is: UPDATE student_details SET 's_name' = 'new name' WHERE 's_id' = '6';
What is the bug here? Please help me understand.
You can't use query parameters for column names (or any other identifer, or SQL keywords, etc.). When you use a query parameter, it is interpreted as a constant value. So your UPDATE statement is executed as if you had written it this way:
UPDATE student_details SET 's_name' = 'new name' WHERE 's_id' = '6';
This does not work. You can't use a string constant value as the left hand side of an assignment*. When I test it in my local MySQL client, I get this error:
ERROR 1064 (42000): 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 ''s_name' = 'new name' WHERE 's_id' = '6'' at line 1
The error reports it got confused at 's_name', because a quoted string literal is not valid at that place in an UPDATE statement.
The WHERE clause is also a problem. It's not a syntax error, but it doesn't do what you probably intended.
WHERE 's_id' = '6';
This compares the string value 's_id' to the string value '6', it does not compare the column s_id to a value. Obviously the string 's_id' is not equal to '6', so the condition will always evaluate as false, and no rows will be updated.
* You can't put a constant value on the left hand of an assignment in most other programming languages, either.
Still new to hibernate custom queries.
My table is
ID TID R1 Position
1 1 1 2
2 1 1 3
I want a custom query to delete rows with TID 1 and R1 1
My current sql looks like
#Query(value = "delete from Table t where t.TID= :tid and t.R1 = :r1", nativeQuery = true)
void deleteByTIDAndR1(#Param("tid") Integer TID, #Param("r1") Integer r1);
It gives me the following error:
.springframework.orm.jpa.JpaSystemException: could not extract ResultSet; nested exception is org.hibernate.exception.GenericJDBCException: could not extract ResultSet] with root cause
My controller retrieves the right tid and r1 ID's.
Is it even possible to delete multiple rows at once? And where could my error be?
Edit
After I add #Modyfying to the query i get the error
TransactionRequiredException: Executing an update/delete query
And after i add #Transactional in combination with #Modifying i get
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 't where t.tid= 1 and t.R1 = 99' at line 1
I think you lack the #Modifying annotation, indicating a query that modify the database:
#Modifying
#Query(value = "delete from Table where TID= :tid and R1 = :r1", nativeQuery = true)
void deleteByTIDAndR1(#Param("tid") Integer TID, #Param("r1") Integer r1);
And yes this method can delete zero, one or more rows.
I'm struggling with following exception:
org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [update EVALUATION_SHEET set STATUS=?, LAST_EDITED=? where id=?]; SQL state [99999]; error code [17004]; Invalid column type; nested exception is java.sql.SQLException: Invalid column type
Which is thrown here:
jdbcTemplate.update("update E_SHEET set STATUS=?, LAST_EDITED=? where id=?",
new Object[]{eSheet.getStatus().ordinal(), eSheet.getLastEditDate(), eSheet.getId()},
new Object[]{OracleTypes.NUMBER, OracleTypes.TIMESTAMP, OracleTypes.NUMBER});
The database table is created as follows:
create table E_SHEET (
ID number not null unique,
ID_POSITION number not null,
STATUS number default 0 not null,
ID_EXAMINER number not null,
LAST_EDITED timestamp not null);
I have no idea what is causing the problem. This method:
eSheet.getLastEditDate()
returns java.util.Date object. I am using Spring JDBC template with Spring Boot and Oracle DB 12c as a datasource.
after the spring documentation http://docs.spring.io/spring/docs/current/spring-framework-reference/html/jdbc.html, an update would work like this:
jdbcTemplate.update("update t_actor set last_name = ? where id = ?", "Banjo", 5276L);
or like this
jdbcTemplate.update("update orders set shipping_charge = shipping_charge * ? / 100 where id = ?", pct, orderId);
But you are passing arrays of Objects as parameters to the method.
Why not just this?
jdbcTemplate.update("update E_SHEET set STATUS=?, LAST_EDITED=? where id=?", eSheet.getStatus().ordinal(), eSheet.getLastEditDate(), eSheet.getId());
I'm playing with the JDBC/MySQL 5.1. I created an insert query to insert some data into a table and want to return the generated key from the newly created row. However, when I go to reference the column by "id" which is my PK and auto-increment column.
PreparedStatement ps = St0rm.getInstance().getDatabase("main")
.prepare("INSERT INTO quests (name,minlevel,start_npc,end_npc) VALUES(?,?,?,?)", true); // creates a prepared statement with flag RETURN_GENERATED_KEYS
// ...
int affected = ps.executeUpdate();
ResultSet keys = ps.getGeneratedKeys();
if (affected > 0 && keys.next()) {
St0rm.getInstance().getLogger().warning(String.format("ID Column Name: %s", keys.getMetaData().getColumnName(1))); // says the column name is: GENERATED_KEY
q = new Quest(keys.getInt(1)); // column index from the generated key, no error thrown.
q = new Quest(keys.getInt("id")); // actual column name, line throws a SQLException
// ...
}
So, my question: Why does ResultSet.getGeneratedKeys use GENERATED_KEY as the column name?
You shouldn't retrieve these columns by name. Only by index, since
there can only ever be one column with MySQL and auto_increments that
returns value(s) that can be exposed by Statement.getGeneratedKeys().
Currently the MySQL server doesn't return information directly that
would make the ability to retrieve these columns by name in an
efficient manner possible, which is why I'm marking this as "to be
fixed later", since we can, once the server returns the information in
a way that the driver can use.
From here (in 2006!).
I have an SQL query that i am going to run using a PreparedStatement, and it is
UPDATE tbl_HitsCounter SET count = ? WHERE keyid = (SELECT id FROM tbl_HitsMaster WHERE sitename = '?')
Now when i set the 2nd paramater, which is a string value, i am getting a strange SQLException.
preparedStatement.setInt(1, 99);
preparedStatement.setString(2, masterKey);
As the setString() method is executed, i am getting an SQLException
The column position '2' is out of range. The number of columns for this ResultSet is '1'.
I have no idea what this is about, i havent even executed the executeUpdate() method.
There is only one placeholder in your SQL but you are trying to assign a value for the second. Your problem is that you have quoted the second placeholder, your SQL should look more like this:
UPDATE tbl_HitsCounter
SET count = ?
WHERE keyid = (
SELECT id
FROM tbl_HitsMaster
WHERE sitename = ?
)
Note the lack of quotes in sitename = ?. This is a placeholder: ?. This is an SQL question mark string literal: '?'.