I have a requirement to create a temp table and select on the temp table against Netezza DB in one session.
Tables: abc, def
String query = create temp table MyTemp as select * from abc join def; select col1, col2 from MyTemp;";
boolean result = statement.execute(query);
while(true) {
if(result) {
ResultSet rs = statements.getResultSet();
while(rs.next()) {
//Access result set.
}
} else {
int count = statement.getUpdateCount(); -- CREATE statement output
if(count == -1) {
break;
}
result = statement.getMoreResults();
}
}
I expected to get the updatecount and then a resultset from the statement as I am executing CREATE temp statement followed by SELECT statement.
I get result as true for the first statement(CREATE statement output). But later when statement.getMoreResults gets executed I get false. But according to documentation the statement.getMoreResults returns true for ResultSet output.
I have an alternative solution of splitting the string using semicolon and executing the individual queries using the same statement. But I want to know why the above solution doesn't work.
I'm unsure as to whether the Netezza JDBC driver supports it, or if it will even work with your example queries and existing code, but it looks like you may need to pass allowMultiQueries=true as an option for your JDBC URL.
See this answer for more information.
Related
I have a JDCB program that connects to a MySQL database, and doing things like adding tables, adding entries, removing entries etc.
I have a problem in a test where i wanna do these steps:
Add a entry to my database table.
Check that the entry exists.
Remove the entry.
Verify that the entry no longer exists.
Here is my code:
testConn = database.getConn();
try {
String addEntry = "INSERT INTO HighScore(ID, username, " +
"Score) VALUES" +
"(ID, 'testAddEntry',333)";
st = testConn.createStatement();
st.execute(addEntry);
String findEntry = "SELECT * FROM HighScore WHERE " +
"username='testAddEntry'";
st.execute(findEntry);
assertTrue(st.execute(findEntry));
String deleteEntry = "DELETE FROM HighScore WHERE " +
"username='testAddEntry'";
st.execute(deleteEntry);
String findEntryNow = "SELECT * FROM HighScore WHERE " +
"username='testAddEntry'";
System.out.println(st.execute(findEntryNow));
assertFalse(st.execute(findEntryNow));
} catch (SQLException e) {
e.printStackTrace();
}
And the problem is that assertFalse(st.execute(findEntryNow)); should return false, but it returns true. And when I check the database the entry is not there. ( i have tried to only add and remove it, so that 100% works).
The problem is i want to run a execute that looks for it but verifies that the entry is not there.
You don't say which version of MySQL you are using, but from the docs MySQL Connector/J 5.1
If you do not know ahead of time whether the SQL statement will be a
SELECT or an UPDATE/INSERT, then you can use the execute(String SQL)
method. This method will return true if the SQL query was a SELECT, or
false if it was an UPDATE, INSERT, or DELETE statement. If the
statement was a SELECT query, you can retrieve the results by calling
the getResultSet() method. If the statement was an UPDATE, INSERT, or
DELETE statement, you can retrieve the affected rows count by calling
getUpdateCount() on the Statement instance.
This states that if you use execute to run a SELECT you will always get true.
From this page https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-usagenotes-statements.html
You will actually need to get the result set and confirm it is empty.
You are misinterpreting the meaning of the return value of Statement.execute:
Returns:
true if the first result is a ResultSet object; false if it is an update count or there are no results
A select query always has a result, and that result is a ResultSet, even if it is empty. The "there are no results" in this documentation refers to statements that produce no results at all (no update counts nor result sets).
So the return value of execute(String) does not indicate the presence or absence of rows. If you want to check that, you need to check ResultSet.next(), or - alternatively - query the count and check that that count is 0.
Option 1:
String findEntryNow = "SELECT * FROM HighScore WHERE " +
"username='testAddEntry'";
try (ResultSet rs = st.executeQuery(findEntryNow)) {
assertFalse(rs.next());
}
Option 2
String findEntryCount = "SELECT count(*) FROM HighScore WHERE " +
"username='testAddEntry'";
try (ResultSet rs = st.executeQuery(findEntryNow)) {
assertTrue(rs.next()); // even absence of entries will produce a row
assertEquals(0, rs.getInt(1));
}
I have an assignment where I need to update records using a PreparedStatement. Once the record have been updated as we know update query return count, i.e., number of row affected.
However, instead of the count I want the rows that were affected by update query in response, or at least a list of id values for the rows that were affected.
This my update query.
UPDATE User_Information uInfo SET address = uInfo.contact_number || uInfo.address where uInfo.user_id between ? AND ?;
Normally it will return count of row affected but in my case query should return the ids of row or all the row affected.
I have used the returning function of PostgreSQL it is working but is not useful for me in that case.
i have used returning function of PostgreSQL but is not useful for me
It should be. Perhaps you were just using it wrong. This code works for me:
sql = "UPDATE table1 SET customer = customer || 'X' WHERE customer LIKE 'ba%' RETURNING id";
try (PreparedStatement s = conn.prepareStatement(sql)) {
s.execute(); // perform the UPDATE
try (ResultSet rs = s.getResultSet()) {
// loop through rows from the RETURNING clause
while (rs.next()) {
System.out.println(rs.getInt("id")); // print the "id" value of the updated row
}
}
}
The documentation indicates that we can also use RETURNING * if we want the ResultSet to include the entire updated row.
Update:
As #CraigRinger suggests in his comment, the PostgreSQL JDBC driver does actually support .getGeneratedKeys() for UPDATE statements too, so this code worked for me as well:
sql = "UPDATE table1 SET customer = customer || 'X' WHERE customer LIKE 'ba%'";
try (PreparedStatement s = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
s.execute(); // perform the UPDATE
try (ResultSet rs = s.getGeneratedKeys()) {
while (rs.next()) {
System.out.println(rs.getInt(1)); // print the "id" value of the updated row
}
}
}
Thanks, Craig!
You might be able to use JDBC's support for getting generated keys. See the Connection.prepareStatement(String sql, int[] columnIndexes) API method, then use Statement.getGeneratedKeys() to access the results.
The spec says "the driver will ignore the array if the SQL statement is not an INSERT statement" but I think PostgreSQL's JDBC driver will actually honour your request with other statement types too.
e.g.
PreparedStatement s = conn.prepareStatement(sql, new String[] {'id'})
s.executeUpdate();
ResultSet rs = s.getGeneratedKeys();
Otherwise, use RETURNING, as Gord Thompson describes.
There are two way of doing it
1. by passing an array of column name or index of column prepareStatement
i.e conn.prepareStatement(sql, new String[] {'id','uname'})
and
2. by using Statement.RETURN_GENERATED_KEYS in prepareStatement.
My code is for this i.e as per my requirement i have developed my code you can have a look for better idea.
private static final String UPDATE_USER_QUERY= "UPDATE User_Information uInfo SET address = uInfo.contact_number || uInfo.address where uInfo.user_id between ? AND ?;";
//pst = connection.prepareStatement(UPDATE_USER_QUERY,columnNames);
pst = connection.prepareStatement(UPDATE_USER_QUERY,Statement.RETURN_GENERATED_KEYS);
ResultSet rst = pst.getGeneratedKeys();
List<UserInformation> userInformationList = new ArrayList<UserInformation>();
UserInformation userInformation;
while (rst.next()){
userInformation = new UserInformation();
userInformation.setUserId(rst.getLong("user_id"));
userInformation.setUserName(rst.getString("user_name"));
userInformation.setUserLName(rst.getString("user_lName"));
userInformation.setAddress(rst.getString("address"));
userInformation.setContactNumber(rst.getLong("contact_number"));
userInformationList.add(userInformation);
}
That think i need to achieve in this case.
Hope so this will help you a lot.
I write a little program to admin my video collection.
/*
insert new data set into the table
*/
int next = 0;
rs = st.executeQuery("Select max(category_id) from category;");
if (rs.next()) {
next = rs.getInt(1) + 1;
System.out.println(next);
}
String query = "INSERT INTO category VALUES (" + next + ", 'Mystics', now());";
rs = st.executeQuery(query);
//on this place is the exception thrown
// this will not execute anymore
rs = st.executeQuery("DELETE FROM category WHERE name = 'Mystics';");
The program can select on tables, make joins but insert make trouble.
I try to insert some new data in my table (see Java-code). After the second test the output show me that the data was inserted. But after Insert was an exception thrown.
1 & 2 are the tests from yesterday and today. (3) was inserted but not selected yet.
1 Mystics 2015-07-05
2 Mystics 2015-07-06
3
org.postgresql.util.PSQLException: query produced no result.
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:287)
at postgre_java.Zetcode.main(Zetcode.java:55)
do you have some advises for me?
Do not manipulate data with read statements!
If you want to insert, update, delete data in db use
Statement stmt = conn.createStatement();
stmt.executeUpdate(SQL);
executeQuery returns resultset, but all that INSERT, UPDATE, DELETE can return is number of affected rows and that is what executeUpdate is returning.
And never, never, never*100 use string concatenation in SQL use Prepared statements!
In Java, you use executeQuery for a SELECT statement or some other statement which returns something. If you want to execute an INSERT, UPDATE or DELETE without returning something, you should use executeUpdate().
Statement#executeUpdate() is meant for that purpose
String query = "INSERT INTO category VALUES (" + next + ", 'Mystics', now());";
int noOfRows= st.executeQuery(query)
but it doesnt return a ResultSet , rather the no of rows affected that you could store into an Integer
Also your is highly vulnerable to Sql injection , try using the PreparedStatements to safeguard your code
I'm executing a stored procedure from jdbc. The procedure returns the contents of a table 'out_table' which consists of 2 columns key and value, via select query.
I'm using
String query = "{? = call my_proc}";
try {
stmt = conn.prepareCall(query);
stmt.registerOutParameter(1, Types.JAVA_OBJECT);
boolean results = stmt.execute();
while (results) {
ResultSet rs = stmt.getResultSet();
if(rs.next()) {
System.out.println(rs.getString("MSG"));
System.out.println(rs.getInt("SEQ"));
}
}
I'm not able to get any results. I can see a lot of example that returns only a single field of a table from proc and not the whole table. The type 'Types.JAVA_OBJECT', I'm not sure what to use. For me, the output table fields are string and int, respectively.
What am I doing wrong?
Note : my_proc:
CREATE PROCEDURE my_proc
AS
BEGIN
CREATE TABLE #tmp_table
(
MSG VARCHAR(255),
SEQ INT
)
//Insert contents into #tmp_table
..
..
..
SELECT * FROM #tmp_table ORDER BY SEQ
END
go
Your stored procedure doesn't have an out parameter. It produces a ResultSet instead. So you should remove the out parameter definition in your call:
String query = "{call my_proc}";
try (CallableStatement stmt = conn.prepareCall(query)) {
boolean results = stmt.execute();
while (true) {
if (results) {
// results true means: result is ResultSet
try (ResultSet rs = stmt.getResultSet()) {
if(rs.next()) {
System.out.println(rs.getString("MSG"));
System.out.println(rs.getInt("SEQ"));
}
}
} else {
// results false means: result is update count
// or no more results if updateCount is -1
int updateCount = stmt.getUpdateCount();
if (updateCount == -1) break;
// Do something with update count
}
// Move to next result
results = stmt.getMoreResults()
}
}
I added try-with-resource to correctly close resource as soon as you are done with them, I have also added code to correctly handle multiple results including update counts, which especially in Sybase (and SQL Server) might be a complication if your stored procedure doesn't use SET NOCOUNT ON. Your original code also had an infinite loop.
Note that if(rs.next()) might need to be while (rs.next) if there can be more than one result in the table.
This is java program for SQL statement. I have two queries. Result of the first query is required for second query.
How do I call it in second query?
These results are values for xml tags.
I need to get first query result for this tag
child1.setAttributeNS(xlink,"xlink:type","");
but this is located in 2nd query and if i try to merge those 2 query I get eror resultset closed.
while(rs1.next()){
int i=0,j=0 ,locid,supid;
int lc[]=new int[100];
int sp[]=new int[100];
lc[i] = rs1.getInt(2);
sp[j] = rs1.getInt(1);
lcid=lc[i++];*/
for(i=0;i<loc[i];i++){
for(j=0;j<sup[j];j++){
lcid=lc[i]; spid=sp[j];
System.out.print(spid +" ");
System.out.println(lcid);
String s = (lc[i]==1 ? "simple" : (lc[i]>1 ? "extended" : null));
System.out.println(s); }}}
String querystring=
" ";
rs = stmt.executeQuery(querystring );
while(rs.next()){
Element child1 = doc.createElement("slink");
/
Element element = doc.createElement("loc");
You need to create a brand new and separate Statement for the second ResultSet. Everytime you get a new ResultSet out of a single Statement, every previously opened one will namely be closed.
Replace
rs = stmt.executeQuery(querystring );
by
Statement stmt2 = connection.createStatement();
rs = stmt2.executeQuery(querystring);
Don't forget to add stmt2.close() to the finally block.
Unrelated to the concrete problem, have you considered just JOINing the both queries and using Javabeans to represent the model? This way you end up with a single query and more self-documenting code.