Invalid column index for JDBC insert with sequence number - java

Below is my code:
I'm passing three parameters to method insertRecordIntoTable which will execute JDBC insert query but I'm receiving Invalid column index.
Below are log statements which got printed:
Inside insertRecordIntoTable
ID from sequence 14
Invalid column index
private static void insertRecordIntoTable(String userName, String targetEmail, String siteName) throws SQLException {
Connection dbConnection = null;
PreparedStatement preparedStatement = null;
System.out.println("Inside insertRecordIntoTable ");
String insertTableSQL = "insert into TableName values(?,?,?,?,?)";
try {
dbConnection = getDBConnection();
preparedStatement = dbConnection.prepareStatement(insertTableSQL);
ResultSet srs = preparedStatement.executeQuery("SELECT id_seq.NEXTVAL FROM dual");
if ( srs!=null && srs.next() ) {
int myId = srs.getInt(1);
System.out.println("ID from sequence "+myId);
preparedStatement.setInt(1, myId);
System.out.println("Inserted ID value "+myId);
srs.close();
}
preparedStatement.setString(2, userName);
System.out.println("Inserted username value "+userName);
preparedStatement.setString(3, targetEmail);
System.out.println("Inserted targetEmail value "+targetEmail);
preparedStatement.setString(4, siteName);
System.out.println("Inserted sitecode value "+siteName);
preparedStatement.setTimestamp(5, getCurrentTimeStamp());
System.out.println("Inserted date value "+getCurrentTimeStamp());
preparedStatement .executeUpdate();
System.out.println("Inserted values ");
System.out.println("Inserted name & email into the table...");
// execute insert SQL stetement
preparedStatement.executeUpdate();
System.out.println("Record is inserted into DBUSER table!");
} catch (SQLException e) {
System.out.println(e.getMessage());
} finally {
if (preparedStatement != null) {
preparedStatement.close();
}
if (dbConnection != null) {
dbConnection.close();
}
}
}

You are using the same PreparedStatement variable twice
preparedStatement.executeQuery("SELECT id_....);
Create and use another variable for this Query else the original Query will be overwritten.
Also consider what is going to happen if
if ( srs!=null && srs.next() ) {
returns false

Related

How to copy data from one table to another and then delete that data in first table using Java?

Two tables are present in the database, one is Student table with columns roll_no(PK), name, grade and DOB, another table StudentLeft with columns roll_no, name, grade and leaving_date.
I want to delete the record of the student from Student table whose roll no is entered by the user, and add the roll no, name, grade and leaving_date (the date when the record is deleted and added to the table) to StudentLeft table.
This is my method.
public static void main(String[] args) throws SQLException {
Connection connection = null;
PreparedStatement preparedStatement = null, preparedStatement1 = null, preparedStatement2 = null;
ResultSet resultSet = null;
String selectQuery = "", updateQuery = "", deleteQuery = "";
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
connection = dataSource.getConnection();
}
catch (ClassNotFoundException e) {
e.printStackTrace();
}
catch (SQLException e) {
e.printStackTrace();
}
int rollNo = Integer.parseInt(args[0]);
try {
selectQuery = "SELECT name, grade FROM Student WHERE roll_no = ?";
updateQuery = "INSERT INTO StudentLog values WHERE roll_no = ?, name = ?, standard = ?";
deleteQuery = "DELETE Student WHERE roll_no = ?";
connection.setAutoCommit(false);
preparedStatement = connection.prepareStatement(selectQuery);
preparedStatement.setInt(1, rollNo);
resultSet = preparedStatement.executeQuery();
preparedStatement1 = connection.prepareStatement(updateQuery);
preparedStatement1.setInt(1, rollNo);
while (resultSet.next()) {
String name = resultSet.getString("name");
String grade = resultSet.getString("grade");
preparedStatement1.setString(2, name);
preparedStatement1.setString(3, grade);
preparedStatement1.addBatch();
}
preparedStatement1.executeBatch();
preparedStatement2 = connection.prepareStatement(deleteQuery);
preparedStatement.setInt(1, rollNo);
connection.commit();
}
catch (SQLException e) {
e.printStackTrace();
}
try {
if (!preparedStatement.isClosed() || !preparedStatement1.isClosed() || !preparedStatement2.isClosed()) {
preparedStatement.close();
preparedStatement1.close();
preparedStatement2.close();
}
if (!connection.isClosed())
connection.close();
}
catch (SQLException e) {
e.printStackTrace();
}
}
These are the errors.
java.sql.BatchUpdateException: ORA-00936: missing expression
at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:10500)
at oracle.jdbc.driver.OracleStatementWrapper.executeBatch(OracleStatementWrapper.java:230)
at Q3.main(Q3.java:48)
Exception in thread "main" java.lang.NullPointerException
at Q3.main(Q3.java:62)
I am using oracle 11g express database.
The code you've written can be simplified quite a bit:
public static void main(String[] args) {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
}
catch (ClassNotFoundException e) {
e.printStackTrace();
return;
}
int rollNo = Integer.parseInt(args[0]);
try (Connection connection = dataSource.getConnection()) {
connection.setAutoCommit(false);
String transferStatement = "INSERT INTO StudentLog (roll_no, name, standard, leaving_date) " +
"SELECT roll_no, name, standard, SYSDATE FROM Student WHERE roll_no = ?";
try (PreparedStatement stmt = connection.prepareStatement(transferStatement)) {
stmt.setInt(1, rollNo);
stmt.executeUpdate();
}
String deleteStatement = "DELETE FROM Student WHERE roll_no = ?";
try (PreparedStatement stmt = connection.prepareStatement(deleteStatement)) {
stmt.setInt(1, rollNo);
stmt.executeUpdate();
}
connection.commit();
}
catch (SQLException e) {
e.printStackTrace();
}
}
I've used try-with-resources statements, which simplifies the clean-up of connections and prepared statements: the connection and statements will get closed when the code inside the try (...) block finishes executing.
Transferring data from the Student table to the StudentLog table can be done in one go with an INSERT INTO ... SELECT statement. This statement doesn't return any result set: there's nothing to iterate through, we just execute it and the row gets inserted.
The DELETE statement is similar: it too returns no result set. I've added the keyword FROM to it out of convention more than anything else: as pointed out on another answer, FROM is optional.
I've also moved the catch (SQLException e) block to the end: that will handle all SQLExceptions generated when connecting to the database or executing either of the prepared statements.
I've kept the code that attempts to load the Oracle database driver class, but added a return statement in the catch block: if there's an exception, the driver isn't on the classpath and connecting to the database is guaranteed to fail so we may as well stop. However, for recent versions of the Oracle driver you don't need this check. Experiment with it: see if the code works without this check and if so, remove it.
Shouldn't your query be
DELETE FROM Student WHERE roll_no = ?
instead of
DELETE Student WHERE roll_no = ?
Your DELETE code used the wrong prepared statement, missing an execute.
It is advisable to use try-with-resources as below, for the automatic closing,
even on return or exception. (It also takes care of variable scopes.)
public static void main(String[] args) throws SQLException {
int rollNo = Integer.parseInt(args[0]);
// Better statements possible.
final String selectQuery = "SELECT name, grade FROM Student WHERE roll_no = ?";
final String updateQuery =
"INSERT INTO StudentLog VALUES WHERE roll_no = ?, name = ?, standard = ?";
final String deleteQuery = "DELETE FROM Student WHERE roll_no = ?";
try { // Check whether you need this. It is for the old discovery mechanism.
Class.forName("oracle.jdbc.driver.OracleDriver");
}
catch (ClassNotFoundException e) {
throw new IllegalStateException("Database driver not provided", e);
}
try (Connection connection = dataSource.getConnection()) {
connection.setAutoCommit(false);
try (PreparedStatement preparedStatement =
connection.prepareStatement(selectQuery)) {
preparedStatement.setInt(1, rollNo);
try (ResultSet resultSet = preparedStatement.executeQuery()) {
try (PreparedStatement preparedStatement1 =
connection.prepareStatement(updateQuery)) {
preparedStatement1.setInt(1, rollNo);
while (resultSet.next()) {
String name = resultSet.getString("name");
String grade = resultSet.getString("grade");
preparedStatement1.setString(2, name);
preparedStatement1.setString(3, grade);
preparedStatement1.addBatch();
}
preparedStatement1.executeBatch();
}
}
}
try (PreparedStatement preparedStatement2 =
connection.prepareStatement(deleteQuery)) {
preparedStatement2.setInt(1, rollNo); // NOT preparedStatement
preparedStatement2.executeUpdate();
}
connection.commit();
}
}
Then one should SELECT+INSERT to the database, using one statement (INSERT SELECT).
The SQL of the StudentLog is a bit incomprehensible to me, but a nice INSERT would be:
INSERT INTO StudentLog VALUES(roll_no, name, standard)
SELECT roll_no, name, grade
FROM Student
WHERE roll_no = ?
Removing the need java nesting of database accesses.

How to fix "Declaration, final or effectively final variable expected" in a PreparedStatement.setString

The problem is that I am trying to set a wild card in a PreparedStatement but the setString statement is giving me the error above.
I have tried changing it to a setObeject statement with multiple different types like Types.VARCHAR. I have tried declaring the PreparedStatement in different places, and I have tried declaring 'name' in the method and in the class.
public String getTemplateText(String name) {
try (
Connection conn = getConnection();
PreparedStatement stmt = conn.prepareStatement("SELECT templateText FROM TEMPLATE WHERE " +
"templateTag = ?");
stmt.setString(1 , name); // this is the line that has the problem!
ResultSet rs = stmt.executeQuery()
) {
System.out.println("Set Text...");
String tempText = rs.getString("templateText");
return tempText;
} catch (SQLException e) {
e.printStackTrace();
}
return "";
}
/* this is the SQL code for the table that I am trying to query */
CREATE TABLE TEMPLATE
(
templateID INTEGER PRIMARY KEY IDENTITY(1,1)
, templateText TEXT
, templateTag CHAR(25)
);
You can't set the stmt parameter in your try-with-resources (because binding the parameter is void and not closable). Instead, you can nest a second try-with-resources after you bind the parameter. Like,
public String getTemplateText(String name) {
try (Connection conn = getConnection();
PreparedStatement stmt = conn
.prepareStatement("SELECT templateText FROM TEMPLATE WHERE " +
"templateTag = ?")) {
stmt.setString(1, name);
try (ResultSet rs = stmt.executeQuery()) {
System.out.println("Set Text...");
String tempText = rs.getString("templateText");
return tempText;
}
} catch (SQLException e) {
e.printStackTrace();
}
return "";
}

Retrieve auto_increment value of multiple rows from MySQL in batch mode

There is a mysql table with primary key as id int auto_increment,
I need to insert multiple rows in batch with multiple insert statement, with autocommit disabled, as following:
SET autocommit=0;
INSERT INTO dummy(NAME, `size`, create_date) VALUES('test', 1, NOW());
INSERT INTO dummy(NAME, `size`, create_date) VALUES('test', 2, NOW());
COMMIT;
Is it possible to get each generated id, instead of only the last id.
If yes, when was each id generated, and how to get all the ids via jdbc?
Thx.
If you want to retrieve the AUTO_INCREMENT keys via JDBC you need to use the JDBC features for doing so (RETURN_GENERATED_KEYS and .getGeneratedKeys()), like this:
try (Connection conn = DriverManager.getConnection(myConnectionString, "root", "beer")) {
try (Statement st = conn.createStatement()) {
st.execute(
"CREATE TEMPORARY TABLE dummy (" +
"`id` INT AUTO_INCREMENT PRIMARY KEY, " +
"`NAME` VARCHAR(50), " +
"`size` INT, " +
"`create_date` DATETIME " +
")");
}
conn.setAutoCommit(false);
System.out.println("AutoCommit is OFF.");
String sql = "INSERT INTO dummy(NAME, `size`, create_date) VALUES('test', ?, NOW())";
try (PreparedStatement ps = conn.prepareStatement(
sql,
PreparedStatement.RETURN_GENERATED_KEYS)) {
// first batch
ps.setInt(1, 1); // `size` = 1
ps.addBatch();
ps.setInt(1, 2); // `size` = 2
ps.addBatch();
ps.executeBatch();
System.out.println("First batch executed. The following AUTO_INCREMENT values were created:");
try (ResultSet rs = ps.getGeneratedKeys()) {
while (rs.next()) {
System.out.println(rs.getInt(1));
}
}
try (Statement st = conn.createStatement()) {
sql = "SELECT COUNT(*) AS n FROM dummy";
try (ResultSet rs = st.executeQuery(sql)) {
rs.next();
System.out.println(String.format("The table contains %d row(s).", rs.getInt(1)));
}
}
conn.rollback();
System.out.print("Transaction rolled back. ");
try (Statement st = conn.createStatement()) {
sql = "SELECT COUNT(*) AS n FROM dummy";
try (ResultSet rs = st.executeQuery(sql)) {
rs.next();
System.out.println(String.format("The table contains %d row(s).", rs.getInt(1)));
}
}
// second batch
ps.setInt(1, 97); // `size` = 97
ps.addBatch();
ps.setInt(1, 98); // `size` = 98
ps.addBatch();
ps.setInt(1, 99); // `size` = 99
ps.addBatch();
ps.executeBatch();
System.out.println("Second batch executed. The following AUTO_INCREMENT values were created:");
try (ResultSet rs = ps.getGeneratedKeys()) {
while (rs.next()) {
System.out.println(rs.getInt(1));
}
}
}
try (Statement st = conn.createStatement()) {
sql = "SELECT COUNT(*) AS n FROM dummy";
try (ResultSet rs = st.executeQuery(sql)) {
rs.next();
System.out.println(String.format("The table contains %d row(s).", rs.getInt(1)));
}
}
}
... which produces the following console output:
AutoCommit is OFF.
First batch executed. The following AUTO_INCREMENT values were created:
1
2
The table contains 2 row(s).
Transaction rolled back. The table contains 0 row(s).
Second batch executed. The following AUTO_INCREMENT values were created:
3
4
5
The table contains 3 row(s).

Sequential JDBC statement executions not transacting

I have the following tables:
all_app_users
=============
all_app_user_id INT PRIMARY KEY NOT NULL
is_enabled BOOLEAN NOT NULL
myapp_users
===========
myapp_user_id INT PRIMARY KEY NOT NULL
all_app_user_id INT FOREIGN KEY (all_app_users)
myapp_user_stage INT NOT NULL
And the following JDBC code:
Long allAppUserId = null;
Long myAppId = null;
Connection pooledConn = getPooledDBConnection();
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = pooledConn.prepareStatement("INSERT INTO all_app_users ( is_enabled ) VALUES ( ? )");
ps.setBoolean(1, true);
ps.execute();
ps.close();
ps = pooledConn.prepareStatement("SELECT IDENT_CURRENT('all_app_users')");
rs = ps.executeQuery();
allAppUserId = (long)rs.getInt(0);
rs.close();
ps = pooledConn.prepareStatement("INSERT INTO myapp_users ( all_app_user_id, myapp_user_stage ) VALUES( ?, ? )");
ps.setInt(1, Ints.checkedCast(allAppUserId));
ps.setInt(2, 5);
ps.execute();
ps.close();
ps = pooledConn.prepareStatement("SELECT IDENT_CURRENT('myapp_users')");
rs = ps.executeQuery();
myAppId = (long)rs.getInt(0);
pooledConn.commit();
System.out.println("Ping");
} catch(SQLException sqlExc) {
logger.error(ExceptionUtils.getStackTrace(sqlExc));
if(pooledConn != null) {
try {
pooledConn.rollback();
} catch (SQLException e) {
logger.error(ExceptionUtils.getStackTrace(e));
}
}
} finally {
try {
if(rs != null) {
rs.close();
}
if(ps != null) {
ps.close();
}
if(pooledConn != null) {
pooledConn.close();
}
} catch (SQLException e) {
logger.error(ExceptionUtils.getStackTrace(e));
}
}
System.out.println("Pong");
When I run that code, I don't get any exceptions, and the "Ping" and "Pong" messages print to STDOUT, however myAppId is NULL. I'm wondering why?
Perhaps it has to do with my use of transactions/commits? Should I be committing after each of the 4 sequential SQL statements? Am I using the JDBC API incorrectly?
Unlike SCOPE_IDENTITY, IDENT_CURRENT does not care about transactions or scope: it returns the last identity key that has been generated for the table.
IDENT_CURRENT can return NULL when the table has no identity column, never contained rows, or has been truncated. None of this applies in your situation. However, it looks like you are running the scalar query incorrectly: you never call rs.next() before calling rs.getInt(...):
ps = pooledConn.prepareStatement("SELECT IDENT_CURRENT('all_app_users')");
rs = ps.executeQuery();
rs.next(); // <<== Add this line
allAppUserId = (long)rs.getInt(0);
rs.close();
ps = pooledConn.prepareStatement("INSERT INTO myapp_users ( all_app_user_id, myapp_user_stage ) VALUES( ?, ? )");
ps.setInt(1, Ints.checkedCast(allAppUserId));
ps.setInt(2, 5);
ps.execute();
ps.close();
ps = pooledConn.prepareStatement("SELECT IDENT_CURRENT('myapp_users')");
rs = ps.executeQuery();
rs.next(); // <<== Add this line
myAppId = (long)rs.getInt(0);

column not allowed here oracle with getText

I tried to save / edit / delete a new row in the database. writing in the gui values to be saved with getText ()
here is the code
Connection conn = Connessione.ConnecrDb();
Statement stmt = null;
ResultSet emps = null;
try{
String sql;
sql = "INSERT INTO PROGETTO.LIBRO (ISBN, DISPONIBILITA, TITOLO, CASA_EDITRICE, CODICE_AUTORE, GENERE, PREZZO)"
+ "VALUES (txt_isbn, txt_disp, txt_titolo, txt_casa, txt_autore, txt_genere, txt_prezzo)";
stmt = conn.createStatement();
emps = stmt.executeQuery(sql);
String ISBN= txt_isbn.getText();
String DISPONIBILITA= txt_disp.getText();
String TITOLO= txt_titolo.getText();
String CASA_EDITRICE= txt_casa.getText();
String CODICE_AUTORE= txt_autore.getText();
String GENERE= txt_genere.getText();
String PREZZO = txt_prezzo.getText();
JOptionPane.showMessageDialog(null, "SALVATO");
}catch(SQLException | HeadlessException e)
{
JOptionPane.showMessageDialog(null, e);
}
finally
{
try{
if (emps != null)
emps.close();
}
catch (SQLException e) { }
try
{
if (stmt != null)
stmt.close();
}
catch (SQLException e) { }
}
Getting this error: column not allowed here
Above code just takes care of insert operation. How can I delete and modify table record?
You have asked 2 different questions here
1. Column not allowed here
This happened because you have not passed values for any of parameter into insert statement.
I am not sure about your requirement however I will use PreparedStatement for this scenario.
Example
String insertTableSQL = "INSERT INTO DBUSER"
+ "(USER_ID, USERNAME, CREATED_BY, CREATED_DATE) VALUES"
+ "(?,?,?,?)";
PreparedStatement preparedStatement = dbConnection.prepareStatement(insertTableSQL);
preparedStatement.setInt(1, 11);
preparedStatement.setString(2, "MindPeace");
preparedStatement.setString(3, "system");
preparedStatement.setTimestamp(4, getCurrentTimeStamp());
preparedStatement .executeUpdate();
2. This code is only to save the data, delete, and modify an entire row how can I do?
Answer is very simple. You have to write code for the same :)
You need 3 SQL statement which has DELETE and UPDATE operation just like insert in above example.
String sql = "INSERT INTO PROGETTO.LIBRO (ISBN, DISPONIBILITA, TITOLO, "
+ "CASA_EDITRICE, CODICE_AUTORE, GENERE, PREZZO)"
+ "VALUES (?, ?, ?, ?, ?, ?, ?)";
try (PreparedStatement stmt = conn.createStatement()) {
NumberFormat numberFormat = NumberFormat.getInstance(Locale.ITALY);
String ISBN = txt_isbn.getText();
String DISPONIBILITA = txt_disp.getText();
String TITOLO = txt_titolo.getText();
String CASA_EDITRICE = txt_casa.getText();
String CODICE_AUTORE = txt_autore.getText();
String GENERE = txt_genere.getText();
BigDecimal PREZZO = new BigDecimal(
numberFormat.parse(txt_prezzo.getText()).doubleValue())
.setScale(2);
stmt.setString(1, ISBN);
stmt.setString(2, DISPONIBILITA);
stmt.setString(3, TITOLO);
stmt.setString(4, CASA_EDITRICE);
stmt.setString(5, CODICE_AUTORE);
stmt.setString(6, GENERE);
stmt.setBigDecimal(7, PREZZO);
int updateCount = stmt.executeUpdate();
JOptionPane.showMessageDialog(null, "SALVATO");
} catch(SQLException | HeadlessException e) {
JOptionPane.showMessageDialog(null, e);
}
Try-with-resources closes the stmt automatically.
The prepared statement replaces the value in the SQL with something like:
INSERT INTO table(column1, colum2, ....)
VALUES('De\'l Rey',
1234.50,
...)
for:
"De'l Rey"
1.234,50
updateCount should be 1 on success.
Wooow..true!!
I created three buttons to delete / update / insert and now it all works and automatically updates the tables.
you've been very very great. Thank you very much.
one last thing.
if I wanted to insert an error message when I delete / update etc "book not found" I tried to create an if:
Boolean found = false;
try{
sql= delete......
etc
if (!found)
JOptionPane.showMessageDialog(null, "NOT FOUND","ERRORE",JOptionPane.WARNING_MESSAGE);
etc...
Connection conn = Connessione.ConnecrDb();
Statement stmt = null;
ResultSet emps = null;
try{
String sql= "DELETE FROM progetto.libro WHERE isbn =?"; /
pst=(OraclePreparedStatement) conn.prepareStatement(sql);
pst.setString (1, txt_isbn.getText());
pst.execute();
JOptionPane.showMessageDialog(null, "ELIMINATO");
Update_table();
txt_isbn.setText("");
txt_disp.setText("");
txt_titolo.setText("");
txt_casa.setText("");
txt_autore.setText("");
txt_genere.setText("");
txt_prezzo.setText("");
}
catch (Exception e)
{
JOptionPane.showMessageDialog(null,e);
}
if you find the book must exit the book removed, or "not found". but as I deployed I always come out "deleted". why?
thanks again

Categories

Resources