I am using Oracle JDBC Driver ojdbc6.jar. When executing a PreparedStatement the ResultSet is returned. However when trying to get details back of what has been saved, I am unable to get this and it throws an Exception.
Below is the code:
public Processor {
private Connection connection;
public Processor() throws Exception {
connection = DriverManager.getConnection(url, username, password);
}
public int saveData(String name) throws Exception {
PreparedStatement preparedStatement = connection.prepareStatement(name);
preparedStatement.setString(1, name);
ResultSet resultSet = preparedStatement.executeQuery();
resultSet.next();
String row = resultSet.getString("NAME");
return resultSet.getRow();
}
public static void main(String[] args) throws Exception {
Processor processor = new Processor();
int row = processor.saveData(new String("INSERT INTO NAMES (name) VALUES (nameTable)"));
}
}
The url, username and password are setup but not shown in the code. I can connect to the Oracle database and persist the data. However, the problem arises when calling resultSet.getString("NAME"). The following Exception is shown:
ORA-009900: invalid SQL statement
java.sql.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:447)
When executing the following code:
ResultSet resultSet = connection.createStatement().executeQuery("SELECT NAME FROM NAMES"));
resultSet.next();
String name = resultSet.getString("NAME");
This works. I have also executed in the SQL describe NAMES and the name attribute is displayed as NAME.
The issue is something to do with the PreparedStatement object returning the ResultSet data.
Any ideas?
EDIT:
ORA-00900: invalid SQL statement
java.sql.SQLSyntaxErrorException
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:447)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:389)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:382)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:675)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:513)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:227)
at oracle.jdbc.driver.T4C8Odscrarr.doODNY(T48COdscrarr.java:98)
at oracle.jdbc.driver.T4CPreparedStatement.doDescribe(T4CPreparedStatement.java:818)
at oracle.jdbc.driver.OracleStatement.getColumnIndex(OracleResultSetImpl.java:3711)
at oracle.jdbc.driver.OracleResultSetImpl.findColumn(OracleResultSetImpl.java:2799)
at oracle.jdbc.driver.OracleResultSet.getString(OracleResultSet.java:498)
at com.example.ProcessorTest.testExecuteInsert(ProcessorTest.java:14)
Your saveData method is the cause because an INSERT does not produce a ResultSet, so executeQuery will produce an error, as there will be no ResultSet.
Also you should only use connection.prepareCall(String) for executing stored procedures, not for other types of statements. For a prepared statement you should use connection.prepareStatement(String).
Change your code to:
public int saveData(String name) throws Exception {
PreparedStatement preparedStatement = connection.prepareStatement(name);
preparedStatement.setString(1, name);
return preparedStatement.executeUpdate();
}
BTW: I hope you are aware that this method uses the parameter name both for the query and as the parameter for the query (which really does not make a lot of sense).
And finally, the new String(...) you do in your main is totally unnecessary.
First of all this line of code
int row = processor.saveData(new String("INSERT INTO NAMES (name) VALUES (nameTable)"));
As you have specified that the method saveData() takes argument as String so there is no need of any new String(...) here and moreover you are using PreparedStatement so you can use parameterized query something like this
int row = processor.saveData("INSERT INTO NAMES (name) VALUES (?)");
Then you can use this statement in saveData()
preparedStatement.setString(1, "name");
Finally you are updating the table not quering it so change this
preparedStatement.executeQuery();
to
return preparedStatement.executeUpdate();
One more thing you should be very specific about your method name. You should always name a method based on what it is going to do. Like saveData() here must be used only for saving data not querying the data as you were trying to do by using the ResultSet. If you want to retrieve the data then use some other method.
Related
I'm working on a simple application that pulls data from a local database. The below code works fine when I use a string for the SQL query, but I can not get it to work with PreparedStatement. I have reviewed similar problems posted here but most of those were caused by doing this, preparedStmt.executeQuery(query); instead of this preparedStmt.executeQuery(); Here is the code,
private final String POSTTITLE= "posttitle"; // DB Column name
private final String POSTCONTENT= "content"; // DB Column name
public String getDbContent(){
try{
String query ="select values(?, ?) from blog";
PreparedStatement preparedStmt = this.connect.prepareStatement(query);
preparedStmt.setString (1,POSTTITLE);
preparedStmt.setString (2,POSTCONTENT);
ResultSet rs = preparedStmt.executeQuery();
rs.next();
return(rs.getString(this.POSTCONTENT)); //Will replace with loop to get all content
} catch(Exception e) {
System.err.println("Error Reading database!");
System.err.println(e);
return("Error: "+e);
}
}
This is the error I get:
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 ''posttitle', 'content') from blog' at line 1
Parameters in prepared statements are for values - you're trying to use them to select fields. They just don't work that way.
In this very specific instance, you'll need to make the SQL dynamic. However, you'll want to make sure that whatever code you have to allow your columns to be specified is tightly constrained to avoid SQL injection attacks. (For example, you could have an enum with the columns in, or a whitelist of allowed values.)
Try concatenating select query:
String query ="select "+POSTTITLE+","+POSTCONTENT+" from blog";
Remember that prepared statements are for values, not query parameters, for them we use simply concatenations.
Try this:
String query ="select POSTTITLE, POSTCONTENT from blog";
PreparedStatement preparedStmt = this.connect.prepareStatement(query);
ResultSet rs = preparedStmt.executeQuery();
rs.next();
There is no need to use field names as parameter.
I have in one java class a method which SELECT one column from a table from my database, and that column is an INT type in the database, and then I selected items from that column, put in a List<Long> and method returns this List. Here is the method:
public List<Long> vratiSveSifreRacuna() throws SQLException {
String sqlVratiSifruRacuna = "SELECT RacunID FROM racun";
Statement stat = konekcija.createStatement();
ResultSet rs = stat.executeQuery(sqlVratiSifruRacuna);
Long racunID = 0L;
List<Long> sifre = new ArrayList<>();
while (rs.next()){
//racunID = rs.getLong("RacunID");
sifre.add(new Long(rs.getInt("RacunID")));
}
return sifre;
}
The problem is, when I start debuging line by line, on this line:
ResultSet rs = stat.executeQuery(sqlVratiSifruRacuna);
it crashes, it jumps on exception. It cannot execute this query and I don't know why, because similar queries it execute well. Do you know what could be the problem? Is the problem maybe because the column I want to select is autoincrement and primary key? I don't know...
Your public (assuming static) method needs the connection object passed into it as an argument as it is not available in the local scope:
public static List<Long> vratiSveSifreRacuna(Connection konekcija) throws SQLException {
String sqlVratiSifruRacuna = "SELECT RacunID FROM racun";
Statement stat = konekcija.createStatement();
ResultSet rs = stat.executeQuery(sqlVratiSifruRacuna);
Otherwise include connection inside local context:
public static List<Long> vratiSveSifreRacuna(String url, String username, String password) throws SQLException {
Connection konekcija = DriverManager.getConnection(url, username, password);
String sqlVratiSifruRacuna = "SELECT RacunID FROM racun";
Statement stat = konekcija.createStatement();
ResultSet rs = stat.executeQuery(sqlVratiSifruRacuna);
I solved the problem finally so I wanted to share the solution. The problem was actually stupid, I accidentally put the code line which makes connection with database below the line where I called this method. So there where the method was called, sql query was actually empty, so it alerts error nullPointerException.
So say a column is named Names I want to get a ArrayList of every variable inside of this column. Example:
Names
Test
Test1
Test3
River
World
Etc
I want to get all of that into an array list. Thanks for the help!
You're not giving much information in your question (e.g. what is the table you'd like to query), so here's a somewhat generic solution:
public List<String> retrieveAllColumnValues(Connection connection) throws SQLException {
String query = "SELECT Names FROM MyTable";
List<String> values = new ArrayList<>();
try (Statement stmt = connection.createStatement()) {
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
values.add(rs.getString("Names"));
}
rs.close();
}
return values;
}
Getting data from the database through JDBC roughly consist of the following parts:
You have a Connection which you use for creating SQL Statements
When you execute the Statement, you get a ResultSet, which contains the values returned by your query
You iterate through the ResultSet and do what you need to with the values
I'm working with java and mysql and I'm facing a problem. I'm trying to create an app with GUI to insert data into mysql table and this is the code :
public void insertuser(String fullname,String salary,String adress,String username,String password) throws SQLException
{
openconnection();
//openconnection method works well
String queryInsert =
"INSERT INTO hema.employee (Emp_name,Emp_salary,Adress,UserName,PassWord)"
+ "VALUES ('"+fullname+"','"+salary+"','"+adress+"','"+username+"','"+password+"')";
Statement stm=(Statement) con.createStatement();
ResultSet rs;
stm.executeQuery(queryInsert);
}
and in the JFrame class I call this method using this code :
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
try {
String NAME =jTextField1.getText();
String SALARY =jTextField2.getText() ;
String ADRESS =jTextField3.getText();
String USER =jTextField4.getText();
String PASS =jPasswordField1.getText();
Employee emp=new Employee();
emp.insertuser(NAME, SALARY, ADRESS, USER, PASS);
} catch (SQLException ex) {
Logger.getLogger(Register.class.getName()).log(Level.SEVERE, null, ex);
}
}
and the first error I have is:
java.sql.SQLException: Can not issue data manipulation statements with executeQuery().
The executeQuery() method is only for executing select statements. For insert, update, and delete statements, you should use the executeUpdate() method.
Executes the given SQL statement, which may be an INSERT, UPDATE, or DELETE statement or an SQL statement that returns nothing, such as an SQL DDL statement.
String sqlInsert =
"INSERT INTO hema.employee (Emp_name,Emp_salary,Adress,UserName,PassWord)"
+ "VALUES (?, ?, ?, ?, ?)";
try (PreparedStatement stm = con.prepareStatement(sqlInsert)) {
stm.setString(1, fullname);
stm-setBigDecimal(2, new BigDecimal(salary));
stm.setString(3, adress);
stm.setString(4, username);
stm.setString(5, password);
int updateCount = stm.executeUpdate(); // 1 when inserted 1 record
} // Closes stm
The error, that for INSERT, DELETE. UPDATE and such executeUpdate should be used is given already.
Also close the statement, for example use the above try-with-resources.
Important is to use a prepared statement. This is a security measure (against SQL injection), but also escapes quotes and backslashes in the values
Another advantage of a prepared statement is that you could reuse it; not so necessary here.
But more important is the type safe setting of fields: I altered the salary field to use BigDecimal, appropriate for numeric values with decimals (SQL column type DECIMAL or so).
I'm trying to insert a new record into an MS SQL database, and I'm getting an exception I've never seen before. When I call executeUpdate the following exception is thrown:
com.microsoft.sqlserver.jdbc.SQLServerException: A result set was generated for update.
This is the Java code that produces the error:
// addComment method adds a new comment for a given requestId
public CommentBean addComment(CommentBean comment) {
PreparedStatement stmt = null;
INative nat = null;
Connection conn = null;
try {
nat = dbConn.retrieveNative();
conn = (Connection)nat.getNative("java.sql.Connection");
stmt = conn.prepareStatement(ADD_COMMENT);
stmt.setInt(1, comment.getRequestId());
stmt.setString(2, comment.getComment());
stmt.setString(3, new SimpleDateFormat("MM/dd/yyyy").format(comment.getDateCreated()));
stmt.setString(4, comment.getCreatedBy());
comment.setCommentId(stmt.executeUpdate()); // exception
} catch(Exception ex) {
System.err.println("ProjectRegistration::SQLDAO - addComment");
ex.printStackTrace();
} finally {
try {
if (stmt != null) stmt.close();
} catch (Exception e) {}
}
return comment;
}// end addComment
Where ADD_COMMENT is defined as a String:
private static final String ADD_COMMENT = "INSERT INTO RequestComments OUTPUT INSERTED.commentId VALUES(?,?,?,?)";
For the sake of being thorough, the table is defined as:
CREATE TABLE RequestComments (
commentId int NOT NULL PRIMARY KEY IDENTITY(1,1),
requestId int FOREIGN KEY REFERENCES Requests(requestId),
comment varchar(400),
dateCreated date,
createdBy varchar(12)
);
I don't think I'm doing anything terribly complicated here, but I can't think of why I'm getting this exception. I have a method in the same class which does the exact same type of insertion (literally the same query with a different table name and number of values), and it has no issues. Does anyone have any ideas on how to resolve this issue?
This particular error can also be caused by an INSERT-trigger, which has a SELECT-statement as a part of the trigger code.
To test whether this is the case, you can try:
using executeQuery(), instead of executeUpdate() - and display the result.
executing the insert in tool like MySQL Workbench, SQL Server Management Studio, or whatever flavour of database design tools are available for your DBMS, to see whether a result is returned.
Related: sql server error "A result set was generated for update"
I'm hoping this may help others looking at the same error message, as it did for me. My solution was to live with a call to executeQuery(), although it only handles an underlying issue, instead of fixing it.
This instruction stmt.executeUpdate() is not returning the commentId, it returns a ResultSet which you could then get the commentId from. Something like this,
ResultSet rs = stmt.executeQuery(); // Not update, you're returning a ResultSet.
if (rs.next()) {
comment.setCommentId(rs.getInt(1));
}
you are using OUTPUT in your insert query i.e you will get a resultset after your query executes and to hold that you need an object of class ResultSet to hold that data
SqlServer : When SET NOCOUNT is ON, the count is not returned. When SET NOCOUNT is OFF, the count is returned.
Connection conn = DriverManager.getConnection(connectDB,user,pwd);
String sql = " set nocount off;INSERT INTO test (name) values (1)";
PreparedStatement prepareStatement = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
System.out.println(prepareStatement.executeUpdate());
ResultSet generatedKeys = prepareStatement.getGeneratedKeys();
if(generatedKeys.next()){
System.out.println(generatedKeys.getString(1));
}
Related:
set-nocount-on-usage
I've had a similar problem where after a while an insert on a autonumber table would give a "A result set was generated for update." at random. I use connection pooling and somehow the driver can get into a state where executeUpdate in combination with Statement.RETURN_GENERATED_KEYS doesn't work anymore. I found out that in this state an executeQuery does the trick, but in the initial state executeQuery does not work. This lead me to the following workaround:
PreparedStatement psInsert = connection.prepareStatement("INSERT INTO XYZ (A,B,C) VALUES(?,?,?)", Statement.RETURN_GENERATED_KEYS);
ResultSet rs = null;
try {
psInsert.setString(1, "A");
psInsert.setString(2, "B");
psInsert.setString(3, "C");
Savepoint savePoint = connection.setSavepoint();
try {
psInsert.executeUpdate();
rs = psInsert.getGeneratedKeys();
} catch (SQLServerException sqe)
{
if (!sqe.getMessage().equals("A result set was generated for update."))
throw sqe;
connection.rollback(savePoint);
rs = psInsert.executeQuery();
}
rs.next();
idField = rs.getInt(1);
} finally {
if(rs != null)
rs.close();
psInsert.close();
}