I am trying to access the column names of 2 different databases; one is SQL and the other is Oracle. The program compiles fine, but while execution it gives an error for the rsmo(resultset for oracle): stating ResultSet.next was not called.
About the program:
I take the databasenames, ip, userid and pass from a text file and store them in strings before passing it to connection. The aim is to copy data from one database to another, but for now all i am doing is finding the column names and number of columns before insertion. At any point of time, there will only be 2 tables viz one of SQL and the other of oracle, to copy to and from. Hence i have an array of colNames for storing the names of the respective columns.
Code snippet:
Connection CONN_SQL = DriverManager.getConnection(URL_SQL, USER_SQL, PASS_SQL);
Connection CONN_ORA = DriverManager.getConnection(URL_ORA, USER_ORA, PASS_ORA);
DatabaseMetaData dmds = CONN_SQL.getMetaData();
DatabaseMetaData dmdo = CONN_ORA.getMetaData();
ResultSet rsms = dmds.getColumns(null, null, SQLTABLENAME, null);
ResultSet rsmo = dmdo.getColumns(null, null, ORACLETABLENAME, null);
String rs;
int columns=1, columno=1;
while(rsms.next() || rsmo.next()){
if(rsms!=null){
colNames[0][columns]=rsms.getString(4);
System.out.println("colnames:" +colNames[0][columns]);
columns++;}
if(rsmo!=null){
System.out.println(rsmo.getString(1));
colNames[1][columno] = rsmo.getString(4);
System.out.println("columno: "+colNames[1][columno]);
columno++;
}
}
Things i have tried and their failures:
Tried 2 while loops for the 2 result sets, the rsms(SQL one) runs perfectly, returning the column names. But the rsmo(oracle one) does not run. It skips the while loop, but executes any statement before AND after it.
I have tried to make another resultset which just executes a SELECT top 20 query for both SQL and oracle. AGAIN, it works properly with SQL but ORACLE's ResultSet is skipped.
I have tried some solutions from stackoverflow such as:
Setting resultset to first, which results in a runtime exception stating "Exhausted ResultSet".
if(!rs.next()), which also results in an Exhausted ResultSet exception.
I just want to know what i am doing wrong, or a solution is always appreciated. Thanks.
UPDATE:
Found out that the resultset isnt allowed to be iterated more than once. Tried closing the ResultSet of SQL, after use, and then opening the other. Still no use, the Oracle RS is skipped again.
In this code
while(rsms.next() || rsmo.next()){
if rsms.next() is evaluated to true, then rsmo.next() will not even be called and may be false.
In you while loop, when would rsms or rsmo suddenly become null?
while (true) {
boolean foundms = false;
boolean foundmo = false;
if (rsms.next()) {
// do stuff
foundms = true;
}
if (rsmo.next()) {
// do stuff
foundmo = true;
}
if (!foundms && !foundmo) break;
}
If this is still not working, then borrowing try (from Darshan's answer )
ResultSet rsmo = dmdo.getColumns(null, null, ORACLETABLENAME, null);
ResultSetMetaData md = rsmo.getMetaData();
for (int i=1; i<=md.getColumnCount(); i++)
{
System.out.println(md.getColumnName(i));
}
You have put OR condition .Which satifies everytiem and is true for SQL alone. Try to seperate while loop and execute
while(rsms.next()){
if(rsms!=null){
colNames[0][columns]=rsms.getString(4);
System.out.println("colnames:" +colNames[0][columns]);
columns++;}}
while(rsmo.next()){
if(rsmo!=null){
System.out.println(rsmo.getString(1));
colNames[1][columno] = rsmo.getString(4);
System.out.println("columno: "+colNames[1][columno]);
columno++;
}
}
The operator '||' in your while loop works in the way that if first statement was true then he does not check any following statements. It is so called short-circuiting. Try to use single '|' sign or splitting in two separate while loops.
Try using following code for oracle
ResultSet rsmo = dmdo.getColumns(null, null, ORACLETABLENAME, null);
ResultSetMetaData md = rsmo.getMetaData();
for (int i=1; i<=md.getColumnCount(); i++)
{
System.out.println(md.getColumnLabel(i));
}
Hope it helps.
Related
First things first, the snippet. Some strings are in my native language, but it shouldn't matter much:
try (Connection conn = DriverManager.getConnection(ADDR)) {
String randomCode = user.substring(0, Math.min(6, user.length()));
/*
SOME VALIDATION CODE THAT SHOULDN'T MATTER HERE, I TESTED THIS AND
IT WORKS FINE, AND CAN BE REMOVED SAFELY WITH THE SAME ISSUE PERSISTING.
IT JUST CHANGES THE randomCode VARIABLE TO SOMETHING UNIQUE.
*/
PreparedStatement stmt = conn.prepareStatement("INSERT INTO utenti(utente_nome, utente_codice) VALUES(?,?);", new String[] {"utenti.utente_id", "utenti.utente_attivo", "utenti.utente_compilazione"});
stmt.setString(1, user);
stmt.setString(2, randomCode);
int amt = stmt.executeUpdate();
System.out.println(amt); //This prints "1", the row is actually inserted in the database, with all the generated fields looking fine.
if (amt > 0) {
ResultSet user_data_set = stmt.getGeneratedKeys();
if (user_data_set.next()) {
return User.fromResultSet(user_data_set); //user_data_set has no columns
} else {
throw new IllegalStateException("L'utente appena creato non è stato resitituito dal server.");
}
} else {
throw new IllegalStateException("L'utente appena creato non è stato resitituito dal server. (2)");
}
}
I'm adding records to a table on a mysql database I set up on a different machine, and after I add one I need to access to the automatically generated fields, to have an abstraction of the database objects in my program.
My problem: the ResultSet I use in the line with the return instruction is empty. I'm sure the statement is executed correctly, things pop up just fine in the database (including the generated keys), and the User.fromResultSet() method is currently just a stub that prints the contents to console.
I've already looked at the other similar questions, and I've already tried:
Replacing the string array with Statement.RETURN_GENERATED_KEYS
Removing the string array
Having only one String in the array
Using numeric indexes for my columns, replacing the array with an int[]
Anyone that can point me in the right direction? I've been on this for an inhuman amount of time.
I am using the ucanaccess tool to interact with my access database, but I do not know how to display or store the resulting ResultSets as Strings.
Edit: I have tried =System.out.println(resultSetId.getString(1)); but that only returns errors.
ResultSet resultSetId;
String msAccDB = "D://Computer Science//passManager//src//Manager.accdb";
String dbURL = "jdbc:ucanaccess://" + msAccDB;
connection = DriverManager.getConnection(dbURL);
statement = connection.createStatement();
resultSetId = statement.executeQuery("SELECT ID FROM Passwords WHERE ID =
\""+identifier+"\";");
System.out.println(resultSetId.getString(1));
Gives the error Exception in thread "main" net.ucanaccess.jdbc.Ucanaccessenter code hereSQLException: invalid cursor state: identifier cursor not positioned on row in UPDATE, DELETE, SET, or GET statement: ; ResultSet is positioned before first row
Edit: Adding the .next() fixed it, thanks!
ResultSet is positioned before first row
When executeQuery returns the ResultSet it is not pointing at a row of data. You need to call resultSetId.next() in order to retrieve each row. That is often done in the context of a while loop when the ResultSet is expected to return more than one row, e.g.,
while (resultSetId.next()) {
System.out.println(resultSetId.getString(1)); // print value from each row
}
but you can simply call it once if you only expect a single row, e.g.,
if (resultSetId.next()) {
System.out.println(resultSetId.getString(1));
} else {
System.out.println("The ResultSet contained no rows.");
}
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.
I'm having problems getting a SQL count query to return the proper value. I know there are already several questions about this topic already posted, but I'm hoping to get a second pair of eyes look over my code to see if they notice anything I've missed. I've found several examples of similar methods that seem to work, and as far as I can see, mine is the same. Here's my method that calls the SQL query:
public int countAddresses(int id) {
ResultSet rs = null;
Statement st = null;
int count = -1;
try{
st = conn.createStatement();
String countAddress = "SELECT COUNT(*) AS AddressCount from address WHERE contact_id =" + id;
rs = st.executeQuery(countAddress);
count = rs.getInt("AddressCount"); //throwing exception
}
catch(SQLException e) {
e.printStackTrace();
}
return count;
}
No matter what tweaks I make, it always returns -1 because the line that reassigns count throws a SQLException. It's worth noting that all my other methods that contact the database are connecting and returning the proper values, and that my java code calls this method after it has successfully called and returned some of these other methods. If anyone can find an error in my code or needs additional info, please let me know. Thanks.
Additional specs:
Spring MVC
XAMPP with a MySQL db
The reason you get an exception is that you are calling getInt without calling next():
rs = st.executeQuery(countAddress);
if (rs.next()) {
count = rs.getInt("AddressCount");
}
The reason it is illegal to call getInt before calling next is that executeQuery() returns you a reader that is not positioned on the first (in this case, the only) result.
Try using
if( rs.next())
count = rs.getInt(1);
I have one script which fetches around 25.000 different ID values and uses them to make some changes in other table. But the programmer created this code which searches ID (dialid in the code) through the table of 10 million records (line 3) and every query in loop is executing around 1 second. My idea is to fetch last 30 days of records with the SQL and to put it into an array and check only the array.
And my question is, how to do that in Java? Is it the in_array function? I'm solid in PHP, but beginner in Java code...
private Integer getDialId(int predictiveId) {
Integer dialid = null;
StringBuilder sql = new StringBuilder("SELECT dialid from dial where PREDICTIVE_DIALID=");
sql.append(predictiveId); //this predictiveId is calculated in other part of code
ResultSet rsDialId = null;
Statement s1 = null;
try {
s1 = oracle.getConn().createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE, ResultSet.CLOSE_CURSORS_AT_COMMIT);
rsDialId = s1.executeQuery(String.valueOf(sql));
if (rsDialId.next()) {
dialid = rsDialId.getInt("dialid");
}
} catch (SQLException ex) {
Logger.getLogger(MediatelCdrSync.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
if (s1 != null) {
s1.close();
}
if (rsDialId != null) {
rsDialId.close();
}
} catch (SQLException ex) {
Logger.getLogger(MediatelCdrSync.class.getName()).log(Level.SEVERE, null, ex);
}
}
System.out.println("DIALID = " + dialid);
return dialid;
}
Thnx
If you have a performance problem I'd start to see why the query takes one second per execution, if it's database time because the dial table does not have and index on PREDICTIVE_DIALID column you can do very little at the java level.
Anyway the jdbc code reveals some problems especially when used with an oracle database.
The biggest issue is that you are hardcoding your query parameter causing Oracle to re"hard parse" the query every time; the second (minor one) is that the resultset is scrollable and updatable while you need only to load the first row. If you want to make some little modification to your code you should change to somethig like this pseudo code:
PreparedStatement ps =connection.prepareStatement("SELECT dialid from dial where PREDICTIVE_DIALID=?");
for (int i=0;i<10;i++) {//your 25000 loop elements is this one
//this shoudl be the start of the body of your getDialId function that takes also a prepared statement
ps.setInt(1, i);
ResultSet rs=ps.executeQuery();
if (rs.next()) {
rs.getInt("dialid");
}
rs.close();
//your getDialId end here
}
ps.close();
With this minimal java solution you should note a performance increase, but you must chek the performance of the single query since if there is a missing index you cand very little at a java code.
Another solution, more complicated, is to to create a temporart table, fill it with all the 25000 predictiveId values and then issue a query that joins dial and you temporary table; so with one resultset(and one query) you can find all the dialid you need. A jdbc batch insert into the temp table speeds up insertion time noticeably.
If you are planning to fetch less record and store that result in some array then
I think it is better for you to limit your search by creating a view in Database with limited record's (say record for last 2 year's)
And Use that view in your select query
"SELECT dialid from dial_view WHERE PREDICTIVE_DIALID = "
Hope it will help :)