SQL JAVA EE WHERE statement isn't taken into account - java

I connect to a database with something like 50 tables, referenced in a table inside the database. The problem I'm having, is for one of these table, the WHERE statement in the SQL query is simply not taken into account by the query, like it was inexistent. I tried a lot of thing, like using row index instead of row name to reference it in the query. I searched for a while but nobody seems to have had the same problem.
It's strange because it happens in only one query, all the other work just fine, on the same type of data, same WHERE. So the solution is probably dumb, but at this point I need another point of view.
The second query below works just fine, but it's just as if the WHERE statement wasn't there... But the first one achieve is goal as intended.
resultCompare = compareStat.executeQuery("SELECT Nb_doc_Notes, Nb_doc_SQL FROM Comparaison_Replique_Resultats WHERE Table_SQL_associee = '"+tableName+"' ORDER BY ID_Comparatif DESC;");
resultCompare.next();
int numberLines = resultCompare.getInt("Nb_doc_Notes");
numberEntries = resultCompare.getInt("Nb_doc_SQL");
resultCompare.close();
resultCompare = compareStat.executeQuery("SELECT ID_Comparatif FROM Comparaison_Replique_Resultats WHERE Difference = "+REQUIRED_DIFFERENCE+" ORDER BY ID_Comparatif DESC;");
resultCompare.next();
int ID = resultCompare.getInt("ID_Comparatif");
resultCompare.close();
So when I check the "ID_Comparatif", it just get the last one in the table, ignoring the fact that Difference is almost everytime different from REQUIRED_DIFFERENCE (equals to 0 BTW, it's just that during my preliminary testing I tried putting the value in a variable and then concatenating it, just like in others query I have in the program.
Thanks !

Related

How to determine if a table contains a value in SQL?

I feel like I'm missing something very obvious here, but it seems that the only way to go about doing this is to get the value, and then see if it returns a null (empty) value, which I would rather not do.
Is there an equivalent to List.contains(Object o) in SQL? Or perhaps the JDBC has something of that nature? If so, what is it?
I am using Microsoft Access 2013.
Unfortunately I don't have any useful code to show, but here is the gist of what I am trying to do. It isn't anything unique at all. I want to have a method (Java) that returns the values of a user that are stored in the database. If the user has not previously been added to the database, the user should be added, and the default values of the user should be set. Then those newly created values will be returned. If a player has already been added to the database (with the username as the primary key), I don't want to overwrite the data that is already there.
I would also advise against using MS Access for this purpose, but if you are familiar with MS Office applications, the familiar UI/UX structure might help you get your footing and require less time to learn other database environments. However, MS Access tends to be quite limited, and I would advise considering alternative options if available.
The only way to see if an SQL table contains a row with some condition on a column is to actually make an SQL query. I don't see why you wouldn't do that. Just make sure that you have an index on the column that you will be constraining the results on. Also for better speed use count to prevent from retrieving all the data from the rows.
SELECT count(*) FROM foos WHERE bar = 'baz'
Assuming you have an index on the bar column this query should be pretty fast and all you have to do is check whether it returns > 0. If it does then you have rows matching your criteria.
You can use "IF EXISTS" which returns a boolean value of 1 or 0.
select
if(
exists( select * from date1 where current_date()>now() ),
'today > now',
'today is not > now'
) as 'today > now ?' ;
+--------------------+
| today > now? |
+--------------------+
| today is not > now |
+--------------------+
1 row in set (0.00 sec)
Another Example:
SELECT IF(
EXISTS( SELECT col from tbl where id='n' ),
colX, colY
) AS 'result'
FROM TBL;
I'm also new to sql and I'm using Oracle.
In Oracle, suppose we have: TYPE: value.
We can use:
where value not in (select TYPE from table)
to make sure value not exist in the column TYPE of the table.
Don't know if it helps.
You can simply use Query with condition.
For example if you have to check records with particular coloumn, you can use where condition
select * from table where column1 = 'checkvalue'
You can use count property to check the no. of records existing with your specified conditon
select count(*) from table where column1 = 'checkvalue'
I have created the following method, which to my knowledge works perfectly. (Using the java.sql package)
public static containsUser(String username)
{
//connection is the Connection object used to connect to my Access database.
Statement statement = this.connection.createStatement();
//"Users" is the name of the table, "Username" is the primary key.
String sql = "SELECT * FROM Users WHERE Username = '" + username + "'";
Result result = statement.executeQuery(sql);
//There is no need for a loop because the primary key is unique.
return result.next();
}
It's an extremely simple and extremely basic method, but hopefully it might help someone in the future.
If there is anything wrong with it, please let me know. I don't want anyone learning from or using poorly written code.
IMPORTANT EDIT: It is now over half a decade after I wrote the above content (both question and answer), and I now advise against the solution I illustrated above.
While it does work, it prioritizes a "Java-mindset-friendly" approach to SQL. In short, it is typically a bad idea to migrate paradigms and mindsets of one language to another, as it is inevitable that you will eventually find yourself trying to fit a square peg into a round hole. The only way to make that work is to shave the corners off the square. The peg will then of course fit, but as you can imagine, starting with a circle peg in the first place would have been the better, cleaner, and less messy solution.
Instead, refer to the above upvoted answers for a more realistic, enterprise-friendly solution to this problem, especially as I imagine the people reading this are likely in a similar situation as I was when I originally wrote this.

Best practice when setting boolean values in PreparedStarement

So I have a MYSQL db in which boolean values are stored as binary(1). I was to investigate why certain queries were slow even though there was an index on the relevant columns. The issue was that when building the SELECT query, the system was using the setBoolean method of PreparedStatement which, as I understand it, converts the value to MYSQL TINYINT. The query found the correct rows, but never used the index since the index was on a binary column. However, if I instead used the setString method and converted the boolean to a string, namely '0' for false and '1' for true, MYSQL was able to use the index and find the wanted rows fast.
Basically, the first query is what I got when using setBoolean and the second when using setString:
SELECT someColumn FROM table WHERE binaryColumn = 1 //Does not use index
SELECT someColumn FROM table WHERE binaryColumn = '1'//Uses index
In Java the change was this:
PreparedStatement ps1 = ...
ps1.setBoolean(1, true);
...
PreparedStatement ps2 = ...
ps2.setString(1, "1");
...
My question is simply if there is a better way to do this? Everything works fine but for some reason I think the code "smells" but I cant really motivate why.
I prefer always the setBoolean, because of abstraction.
The real interesting point is when your DB uses the index.
The optimizier of the DB use a index only, if it makes sense. If you have 1000 entries and a booleanvalue only split it into 50/50 it make no sense for that index, especial when its not the PK - but if you use a additional limitation, to get only 10 rows, as result, a good optimizer should use the index you specified - maybe a "composed index" on 2 columns (booleanColumn1, StringColumn1)
MySQL uses TINYINT(1) for the SQL BOOL/BOOLEAN. So I would change the data type to BOOLEAN, in accordance to standard SQL.
By your relay, the issue should then be resolved. By the way BIT(1) would be another option.

How to retrieve previously auto-generated PK ID value using JDBC and HSQLDB

I'm working with JDBC and HSQLDB 2.2.9. What's the most efficient and accurate way to insert a new row into a DB and, subsequently, retain its id (PK set to autoincrement) value? The reason I need to do this is probably pretty obvious, but I'll illustrate with an example for discussion:
Say there's a Customer table that has a PersonId field with a FK constraint referring to a row from a Person table. I want to create a new Customer, but to do this I need to first create a new Person and use the new Person.id value to set Customer.PersonId.
I've seen four ways to approach this:
Insert the Person row setting the id field to null. HSQLDB generates the next id value automatically. Then perform a query on the Person table to get the id value just created and use it to create the new Customer row.
This seems expensive just to retrieve a single integer value.
Get the next id value in the Person table and use it in the INSERT statement to set the Person.id value manually. Use the same id value to set Customer.PersonId. No subsequent read from the DB is needed.
Inconsistencies may arise if an id value is obtained, but another connection performs an INSERT in the table before my INSERT INTO Person... statement is executed.
Execute the INSERT statement, as in option 1 above, setting id=null to allow auto-generation. Then use the getGeneratedKeys method to retrieve keys generated in last statement.
I thought this sounded like a good option, but I couldn't get it to work. Here's a snippet of my code:
// PreparedStatement prepared previously...
preparedStatement.executeUpdate();
ResultSet genKeys = preparedStatement.getGeneratedKeys();
int id;
if (genKeys.next()) {
id = genKeys.getInt(1);
}
// Finish up method...
This code was returning an empty ResultSet for genKeys. Am I using the getGeneratedKeys method incorrectly? If I could get this to work, this might be the way to go.
Again, execute the INSERT statement allowing for auto-generated id. Then immediately execute CALL IDENTITY() to retrieve the last id value generated by the connection (as explained here and mentioned in this SO question).
This also seems like a reasonable option, even though I must perform an additional executeQuery. On the positive side, I was actually able to get it to work with the following code:
// INSERT statement executed here...
statement = connection.createStatement();
ResultSet rs = statement.executeQuery("CALL IDENTITY();");
int id;
if (rs.next()) id = rs.getInt(1);
// Finish up method...
So, in summary, the first two options I'm not crazy about. The second two seem ok, but I could only get option 4 to work. Which option is preferred and why? If option 3 is the best, what am I doing wrong? Also, is there a better way that I haven't mentioned? I know words like 'better' can be subjective, but I'm working with a simple DB and want the most direct solution that doesn't open up the DB to possible inconsistencies and doesn't increase the transaction failure rate (due to trying to create a record with an id that already exists).
This seems like a basic question (and essential), but I couldn't find much guidance on the best way to do it. Thanks.
EDIT:
I just found this question that discusses my option 3. According to the accepted answer, it appears I was leaving out the Statement.RETURN_GENERATED_KEYS parameter needed to enable that functionality. I didn't show the prepareStatement method in my code snippet, but I was using the single parameter version. I need to retry using the overloaded, two-parameter version.
There are also a few other SO questions which show up with that question that are closly related to my question. So, I guess mine could be considered a duplicate (not sure how I missed those other questions before). But I'd still like any guidance on whether one solution is considered better than the others. For now, if I get option 3 to work, I'll probably go with that.
I don't have enough reputation to comment on neizan's answer, but here's how I solved the same problem:
The column looked like an ID column, but it wasn't defined as IDENTITY;
As said above, you need to specify RETURN_GENERATED_KEYS.
It looks like if you execute 2 INSERT in sequence, the second one won't return the generated keys. Use "CALL IDENTITY()" instead.
Example using HSQLDB 2.2.9:
CREATE TABLE MY_TABLE (
ID INTEGER IDENTITY,
NAME VARCHAR(30)
)
Then in Java:
PreparedStatement result = cnx.prepareStatement(
"INSERT INTO MY_TABLE(ID, NAME) VALUES(NULL, 'TOM');",
RETURN_GENERATED_KEYS);
int updated = result.executeUpdate();
if (updated == 1) {
ResultSet generatedKeys = result.getGeneratedKeys();
if (generatedKeys.next()) {
int key = generatedKeys.getInt(1);
}
}
Not much action here, so I'll go ahead and answer to bring closure to this question. After playing around with the different options, and after see this question, I was able to get my option 3 to work. Like I mentioned in the edit to my question, I'm going to use option 3. Option 4 also worked fine, but since the accepted answer to the linked question is given by a reputable source, I am sticking with that. I wish I'd have seen that question/answer before starting this one, I'd have saved some time!

If exist return id else insert in postgres [duplicate]

This question already has answers here:
Insert, on duplicate update in PostgreSQL?
(18 answers)
Closed 9 years ago.
I am new to postgres and i'm am having to populate a database using it. I cant submit my actual code for reference but my program is in java and i'm trying to do something along these lines.
IF EXISTS (SELECT 1 FROM TEST WHERE FOO = 2 and BAR = 3)
BEGIN
SELECT TableID FROM TEST WHERE FOO = 2 and BAR = 3
END
ELSE
BEGIN
INSERT INTO TEST(FOO, BAR) VALUES(2, 3)
END
I'm trying to do something along these lines because my program is just parsing a bunch of files and populating the database. I need to ensure that if someone goes back and runs the program again on the same files that the database wont contain duplicate entries. The id associated with this insert/record found is used to populate a linking table. I found this example on another stackoverflow questions only it relates to Microsoft SQL Server 2005. I'm using postgres and it fails on the very first line at IF. I understand different database languages operate slightly different. Is there a way to do an IF EXISTS return ID else insert using postgres.
Currently i'm checking if the entry exist and if it doesnt insert. But then i'm having to query the database again to get the id of the record had it existed.
int id = 0;
PrepareStatement ps = conn.prepare(SQL command, statement.generatekeys); //syntax is not correct for the preparestatement but i'm not looking at my code and dont remember it off top of my head.
ResultSet rs = ps.executeUpdate();
if(rs.next()){
if(rs.getGeneratedKeys().rows() > 0) //not sitting at my code but there is a way to check if a key was generated from an insert
id = rs.getGeneratedKeys()
}else{
id = rs.getInt(1);
}
}
Update Taken from comments:
The better questions is Is there a way to do an if exist return id else insert without querying/checking a where clause twice.
I want to avoid doing a WHERE check twice to get either my id from existing data or from the new entry. My condition checks are rather lengthy as some of my tables contain upwards of 14 attributes. Currently what i do is query the database once doing an INSERT if doesn't exist. If my getGeneratedKeys().size() = 0 i know the INSERT failed because it exist and then I re-query the database with the same where clause from my original query and grab the id.
This is closely related to an UPSERT or MERGE operation, which isn't supported directly by PostgreSQL. Upsert is rather more complicated in a concurrent environment than you'd expect.
Most of the concurrency problems with upsert also apply to what you want to do. Your current code is entirely wrong in the presence of more than one thread doing updates at a time.
Read depesz's article on the topic then search Stack Overflow for [postgresql] upsert or [postgresql] merge, and this SO post I wrote.
You should be able to fairly easily adapt the PL/PgSQL function given there to do the job. It'll only run correctly in READ COMMITTED isolation, though.

How to update sparse values in a database table?

What is the best practice to update a table record most effectively (in my case with a primary key), when not all values are present?
Imagine:
PRIMARY_KEY1, COLUMN_2, COLUMN_3, COLUMN_4, COLUMN_5, COLUMN_6, ...
I always get tuples like (PRIMARY_KEY1, COLUMN_5, COLUMN_4) or (PRIMARY_KEY1, COLUMN_2, COLUMN_6, COLUMN_3) and want to just update them in the fastest way possible without having a database lookup for all other values.
Since I have to to this very fast, I would like to use something like batches for prepared statements in order to prevent massive database requests.
Thanks for all replies!
You can 'cheat' by expecting SQL to fill in the values at row-access time. Eg, this type of statement:
UPDATE MyTable SET (column_1, column_2, ..., column_6)
= (COLAESCE(#suppliedValue1, column_1),
COLAESCE(#suppliedValue2, column_2),
...,
COLAESCE(#suppliedValue6, column_6))
WHERE primary_Key1 = #primaryKey
Then, when filling out the parameters, just leave anything unsupplied null... and you should be good.
you are not required to update the entire row in SQL. just use UPDATEs SET syntax.
UPDATE table SET COLUMN_5 = 'foo', COLUMN_4 = 'goo' WHERE PRIMARY_KEY1 = 'hoo';
See this post here,
JDBC batch insert performance
Read it. Then look on the right column of the page under related links for other similar posts
You should find all the answers you need in no time.

Categories