I have this small piece of code, the scope is:
In the outter while: I calculate a "min" number (selected from the tempTable)
In the inner while: I "Select * from (tempTable) where (some conditions)" (im completly sure there is more than 1 row that matches these conditions) and then i update the min in each row selected (whithin other aspects not relevant)
The inner while is conditioned by rs.next() which (as it does in other parts of my code) it should iterate through every row that matches the condition ("Select * from (tempTable) where (some conditions)")
Basically the program should work as: getting a "min" value, then proceed to update each row with equal "min" and "min" = "min" + 1. So in the next iteration of the outter while the "min" should be 1 more.
Instead, what it does is: get "min" value, then update ONLY the first row that matches that min value and goes back to the outter while(which calculates the min again). In the end, the output is rather the same and it kinda works, but I would really appreciate if it worked as I intended to match other aspects of the program.
I think the problem comes from doing a select * from a TEMPtable which for some reason returns only 1 row (i've been investigating but couldnt find other people with the same issue, so i don't really know). As I mentioned, there is other parts of my code where I do the same select * NORMALtable and the ResultSet.Next() works as intended.
while( total_tfgs > 0 ) {
int tfgs_round = 0;
min = prepareStatement.executeQuery("SELECT MIN("+ PROFESORES_COL_TFGS +") FROM TEMP_TABLA_PROFESORES WHERE " + PROFESORES_COL_OBLIGA + " = 'SÍ'").getInt(1);
ResultSet rs = prepareStatement.executeQuery("SELECT * FROM TEMP_TABLA_PROFESORES WHERE " + PROFESORES_COL_TFGS + " = '" + min + "' AND " + PROFESORES_COL_OBLIGA + " = 'SÍ'");
while(rs.next()) {
prepareStatement.executeUpdate("UPDATE TEMP_TABLA_PROFESORES SET PROFESORES_COL_TFGS = PROFESORES_COL_TFGS + 1 WHERE PROFESORES_COL_ID = '" + rs.getInt(1) + "'");
tfgs_round = tfgs_round + 1;
}
total_tfgs = total_tfgs - tfgs_ronda;
}
Here i place code where it works as i want it to work:
Statement statement = con.createStatement();
ResultSet rsA = statement.executeQuery("SELECT * FROM " + TABLA_ALUMNOS);
while(rsA.next()) {
String idA = String.valueOf(rsA.getInt("ALUMNOS_COL_ID"));
String dniA = rsA.getString("ALUMNOS_COL_DNI");
String nombreA = rsA.getString("ALUMNOS_COL_NOMBRE");
String dataA[] = {idA, dniA, nombreA};
DefaultTableModel tblModel = (DefaultTableModel) table_Alumnos.getModel();
tblModel.addRow(dataA);
table_Alumnos.setModel(tblModel);
}
PD: while redacting this i changed some variables to english (in the first code snipet) so it would be more legible(tfgs_round,total_tfgs), so if there is some misspell or something, thats not the problem. Please focus in the ResultSet select * from TEMP_TABLE (which i didnt change)
Thank you in advance for any help you can provide.
I would not call executeUpdate within the loop that is reading the ResultSet. That means you are using the statement for a second query while it is still involved in the first query. I would finish the first query entirely, close the ResultSet and then perform the update separately. If you really need to do an update while reading a ResultSet, I would build a new statement for it.
Related
i´ve been using java to connect to a remote database in mysql, i´ve done a lot of diferents queries but today i´ve figured out that every time i wanted to look for a result, i have been always storing the result/s in a resulset,although in some cases my queries just have to return 0 or 1 result,that means that is not possible to receive an array of registers that meet the querie, so what kind of variable should i use to store JUST ONE RESULT?
Below i will post a portion of my code that describe the situation, it have to be understood that in the table "tareas", every register have a DIFFERENT title, like a PK.
Thanks in advance...
ps = c.prepareStatement("SELECT * FROM tareas WHERE titulo='" + title + "'");
rr = ps.executeQuery();
while (rr.next()) {
JOptionPane.showMessageDialog(null, "Titulo: " + rr.getString("titulo") + newline +
"Creador: " + rr.getString("nombre") + newline +
"Receptor: " + rr.getString("receptor") + newline +
"Tarea: " + nuevacadena(rr.getString("tarea")) + newline +
"fecha de creación:" + lafecha(rr.getString("fecha")));
}
Add a LIMIT; without that the JDBC driver may pre-fetch more than one row regardless of option 2 (which you can also do). That is,
ps = c.prepareStatement("SELECT * FROM tareas WHERE titulo='" + title + "' LIMIT 1");
and then change (for option 2)
while (rr.next())
to
if (rr.next())
Also, since you are using a PreparedStatement, you should bind your parameters instead of writing them literally into the query; for example,
ps = c.prepareStatement("SELECT * FROM tareas WHERE titulo=? LIMIT 1");
ps.setString(1, title);
Following is the logic in my java code :
con.setAutoCommit(false);
int starIndex = 0;
List Details = new ArrayList();
while (true) {
isRsEmpty = true;
String my_Query = "select * from x,y,z where"
+ " x.a = y.b"
+ " x.a = z.c"
+ "y.b = z.e"
+ " ORDER BY a ASC"
+ " limit 5"
+ " offset " + starIndex;
preparedStatement = con.prepareStatement(my_Query);
rs = preparedStatement.executeQuery();
while (rs.next()) {
isRsEmpty = false;
//Other processing steps
starIndex++;
Details.add(rs.getInt("id"));
}
if(isRsEmpty){
starIndex = 0;
}
Iterator itr = Details.iterator();
String updateTable = "UPDATE x SET status = ? where i = ? and j = ? and k = ?";
updatePreparedStatement = con.prepareStatement(updateTable);
while (itr.hasNext()) {
updatePreparedStatement.setInt(1, 1);
updatePreparedStatement.setString(2, "zzz");
updatePreparedStatement.setInt(3, 9);
updatePreparedStatement.setInt(4, 10);
updatePreparedStatement.addBatch();
}
updatePreparedStatement.executeBatch();
con.commit();
Details.clear();
}
The Problem :
I have 13 entries in my table which meets the select query.
When I first time run the query my Limit is 5 and Offset is 0 and I get
5 records correctly from the table and the selected 5 records are updated.
After doing the update to the table when the select query runs again it gives me 3 records.This is unexpected since I have more 8 records left in the table.Again the 3 records are updated.
Again when the select query runs it gives me 0 records.
Then again a select query runs which gives me 5 records and updates the 5 records.
I am not able to understand this behaviour. If I run my select query without update then it runs correctly which gives me 5,5,3 records , but with the above logic it gives me 5,3,0,5 records.
What is the problem here ?
Note : In the above program all the variables like PreparedStatement and other are declared correctly.
Thank you
Is there any chance you are missing "and" keyword between your conditions in the select query?
String my_Query = "select * from x,y,z where"
+ " x.a = y.b"
+ " AND x.a = z.c"
+ " AND y.b = z.e"
+ " ORDER BY a ASC"
+ " limit 5"
+ " offset " + starIndex;
I don't know if that would solve the problem but I find it weird that it works like this.
I am querying my SQL database and have discovered that when I ask for 160 rows, and the database only has 44 rows, ResultSet returns 160 rows. When this happens, the first 44 rows have actual useful numeric values and the remaining 116 rows have values that are all 0. How do I get ResultSet to only contain or provide me with the 44 rows that are returned from the database query? Here is the code fragment:
statement = connection.createStatement();
query = "SELECT " + "Close" + ", Volume" + " FROM source_data_manager.TradingData_daily WHERE Exchange = '" + exchange +
"' and Symbol = '" + symbol + "' order by EntryID DESC limit " + 160 + ";";
//Execute the query
resultSet = statement.executeQuery(query);
//Loop through the results
int count = 0;
while (resultSet.next())
{
valuesRetrieved[count++] = resultSet.getDouble(1);
volume += resultSet.getLong(2);
}
Coming out of this loop, count is equal to 160 but should equal to 44. The array valuesRetrieved[] has 44 elements of actual usable values, and the remaining 114 values all equal to zero (0). The array should only have 44 values in it.
Try using Statement.setMaxRows
void setMaxRows(int max) throws SQLException;
The advantage of setMaxRows is that you can create general statements, valid for Postgres, Oracle, Mysql etc.
In fact, Oracle is using ROWNUM syntax, postgres - LIMIT, msqsql - TOP.
It's strange, might it be driver specific reaction to limit without fetch size?
What would resultSet.isAfterLast()return for empty rows?
Thank you all for your responses. Nicholas Filotto had the correct answer. In the top of the method is the declaration of valuesRetrieved as follows:
double [] valuesReceived = new double [160];
The problem is fixed by not using the statement:
valuesReceived[count++] = resultSet.getDouble(1);
There is one additional peculiarity. I must not understand what getFetchSize() does because the statement:
int xxx = resultSet.getFetchSize();
always results in 0 being assigned to xxx.... Don't really understand why.
I have the following problem:
I have two tables in one data base which consist of the same columns besides the name of the last column. I want to write data into them using Java.
I want to use the same preparedStatement for both tables, where I check with an if-command whether it is table1 or table2. table2 has amount10 as the name for the last column, table1 has amount20 for it. This number is stored in a variable within my code.
Below you can see a (simplified) example and how I tried to let the column name variable but it doesn't work. Is there any way to fix this without copying the whole statement and manually changing the number variable?
String insertData = "INSERT INTO `database`.`"+table+"`
(`person_id`,`Date`,`amount`+"number") VALUES "+
"(?,?,?) ON DUPLICATE KEY UPDATE " +
"`person_id` = ? , " +
"`Date` = ? , " +
"`amount`+"number" = ? ; ";
PreparedStatement insertDataStmt;
This will not work since variables number and table are not going to be magically injected into your insertData string while you are changing them.
I'd to a method prepareInsertstatement(String table, String number) that would return correct PreparedStatement:
public void prepareInsertStatement(Connection conn, Strint table, String number) {
String insertData = "INSERT INTO `database`.`"+table+"`
(`person_id`,`Date`,`amount+"number"') VALUES "+
"(?,?,?) ON DUPLICATE KEY UPDATE " +
"`person_id` = ? , " +
"`Date` = ? , " +
"`amount+"number"' = ? ; ";
PreparedStatement insertDataStmt = conn.prepareStatement(insertData);
return insertDataStmt;
}
Just remember to close the PreparesStatement when you don't need it any more.
I suppose that reason for that is invalid syntax. When you concatenate string for last column name you use code 'amount' + number. If your number value is 20, than concat result will be
'amount'20 that cause invalid syntax exception. Just move one extra ' after number.
"'amount" + number + "'"
Note: log, or just error that appears during this statement execution would be very useful to find right answer for your question.
I wasnt quite sure how to word the title so sorry about that. I am trying to load some start and stop schedule times into a database but sometimes a start and stop time for the same system will overlap such as one time may be 5:30 to 12:30 and then another time for the same system may be 8:30 to 10:30 I want to avoid inserting that data into the table.
I am using a jdbc and odbc bridge to do this all in a java program, when the user clicks generate schedules it reads all the schedule info from a text file, and then inserts it into the database. When the programs reads the times that are in between already existing times I want to skip doing the insert.
My Ideas so have to been to some how compared the end time i get from the text file with the MAX value of the times in the database and if its less than that value then skip this insert but I dont know how to tie the MAX value into an if statement. Another idea was after im done all the inserts then just delete the rows where the SCHEDULE_TIME is greater than the min value in the SCHEDULE_TIME column and the SCHEDULE_TIME is less than the max value in the SCHEDULE_TIME column.
here is an example of what the data in my table looks like:
SITE_ID ------- DEV_ID ------- SCHEDULE_TIME ------- VALUE_ENUM
---------------------------------------------------------------
1 3000 09:30:00 1
1 3000 15:30:00 0
1 3000 12:30:00 1
1 3000 13:30:00 0
1 3000 16:30:00 1
1 3000 18:30:00 0
the rows alternate from start top to stop time all the rows where VALUE_ENUM are 1 are start times and all the rows where VALUE_ENUM are 0 are stop times. Im trying to delete the time that falls between a other start and stop times in this case delete rows 3 and 4. Keep in mind this tables actually creates hundreds of rows from the text file so I can not just delete it manually, it would be best if I could find a way to just avoid inserting it.
Here is a copy of my current insert method, ignore all the extra columns I use, they are unrelated to the problem, they are just using so I add and delete for the correct systems.
private void Insert() throws SQLException
{
stmt = conn.createStatement();
String sqlStm = "update ARRAY_BAC_SCH_Schedule set SCHEDULE_TIME = {t '" + finalEnd + "'} WHERE SCHEDULE_TIME >= {t '" + finalStart + "'} AND" +
" SCHEDULE_TIME <= {t '" + finalEnd + "'} AND VALUE_ENUM = 0 AND DEV_ID = " + devID + " and INSTANCE = " + instanceNum;
int updateSuccess = stmt.executeUpdate(sqlStm);
if (updateSuccess < 1)
{
sqlStm = "insert into ARRAY_BAC_SCH_Schedule (SITE_ID, DEV_ID, INSTANCE, DAY, SCHEDULE_TIME, VALUE_ENUM, Value_Type) " +
" values (1, " + devID + ", " + instanceNum + ", " + day + ", {t '" + finalStart + "'}, 1, 'Unsupported')";
stmt.executeUpdate(sqlStm);
sqlStm = "insert into ARRAY_BAC_SCH_Schedule (SITE_ID, DEV_ID, INSTANCE, DAY, SCHEDULE_TIME, VALUE_ENUM, Value_Type) " +
" values (1," + devID + ", " + instanceNum + ", " + day + ", {t '" + finalEnd + "'}, 0, 'Unsupported')";
stmt.executeUpdate(sqlStm);
}
if(stmt!=null)
stmt.close();
}
I hope I explained this enough, sorry if the question is unclear.
I have also posted this question under sql tags to see if someone knows a way to do it with just sql.
Update: I had it working before by taking the last start and end time entering and then when I go to enter 2 new times I checked to see that the new start time was >= the previous one and that the new end time <= the previous end time and if they were I would skip the insert.
However I have had to make some changes to the program which I can no longer get the previous start/end time, my idea now is if I can select the last 2 times in the table and saved them to a variable on the java side and then do the same comparison I did before
I think the problem is with your design. If your text file is relying in the order you shouldn't be saving as is in the database.
I would have store that information in just one record. For example instead of having VALUE_ENUM and two records in the database you will just need one record with the following fields START_SCHEDULE_TIME and END_SCHEDULE_TIME. Now with that design you could just do a select like this:
select count(*) from ARRAY_BAC_SCH_Schedule where finalStart >=
START_SCHEDULE_TIME and finalEnd <= END_SCHEDULE_TIME
if the select returns 1 then you just skip and don't insert.
Is it fair to say that the problem area is characterised/identified by 2 or more consecutive start times? I suspect it is.
If that is the case then perhaps just load everything you have into the table, then parse the table in time order. Each time you encounter 2 consecutive start times you know you must delete 'this' start/end pair.
Of course if you encounter a THIRD start time in a row you know you have to delete 2 end times.
so in pseudocode - The dataset is ordered by Dev_Id, schedule_time, value_enum desc
int NestCount = 0;
int CurrDevId = 0;
for each record
{
// Optional DevId Logic Starts Here
if ThisRecord.DevId <> CurrDevId then
{
if NestCount <> 0
{
CurrDevId = 0;
RollBack;
Shriek("Cannot Proceed Because The Data Are Fubar");
}
else
{
CurrDevId = ThisRecord.DevId;
}
} // And Ends Here
if
CurrDevId <> 0 && // Optional DevId Logic
IsAStartRecord()
{
If NestCount > 0
{
DeleteThisRecord();
}
NestCount += 1;
}
else // Is an end record
{
NestCount -= 1;
If NestCount > 0
{
DeleteThisRecord();
}
}
}
If it is possible to implement this as a stored procedure I probably would.
Does that help ?
thanks for the help, but I ended up just doing a string replace on the : in the time and made it into a . then converted it to a double and saved that time into a temp variable and then the next time I had times for that system I checked if the start time was greater than the last start time and if the end time was less than the last one so if they fell between I could avoid adding, not 100% tested but it worked for the first system I tried