how can i implement haskey() function with a query in mysql - java

I'm translating a program form python to java and I'm working with mysql
at some point I have to check in my db if I have data with a special key.
let's say
if(namesTable.haskey(24))
doSoemthing();
I don't need any retrieved data from db I just want to see if there is anything with this special key or not. Additionally, I dont want to use COUNT because using count means to go through all the db and give me a number like 248 while I just care if there is any or not.
I want something to give me a yes as soon as it finds a match in database.

(I interpreted the "check in my db if I have data with a special key" to mean that you are checking a single column in a single table for the existence of a particular value. That seems to be the most straightforward interpretation.)
If you need to check a table to see if a row exists in a particular table, with a particular value in a particular column, the most efficient query might be:
SELECT 1
FROM DUAL
WHERE EXISTS (SELECT 1
FROM mytable t
WHERE t.key = 24
)
The pseudo table DUAL is guaranteed to return no more than one row, and the EXISTS subquery will "exit" with TRUE as soon as one row is found.
For best performance, you'll want an index with key as the leading column, e.g.
ON mytable (key)

I would recommend to use a flag in your application, like:
Boolean hasKey = false;
On startup of your program, you need to run the sql query against namesTable just once to check if it has the special key and on the basis of that query result set the hasKey. From then and onwards you don't need to check the db again, and you can simply use:
if(hasKey)
{
soSomething();
}
On add/update of a record in namesTable, check if it has special key, if yes then set the hasKey flag to true.

Related

JDBC PreparedStatement in batch when columns to set vary from row to row

I am trying to batch updates using PreparedStatement where the data you get in varies in what you have available.
Simple example:
You have a table with column x and y. Your inputdata is a representation of rows where only the modified column is present. So for row 1 you have x='foo' and for row 2 you have y='bar'. In order to batch these with a PreparedStatement you need one SQL statement: "update table where x=?,y=? where etc".
The solution that I am working towards is setting the column where you dont have any value to the value that is already present, but I'm not sure if this is possible. In raw SQL you could write "update table where x=x and y='foo' where etc", however I haven't found any ways to achieve this by setting the "?" parameter to be a reference to the column, it seems it's not possible.
Is it possible to handle this case at all with PreparedStatements? I apologize if my explanation is poor.
Assuming the values you want to set are all non-null, you could use a statement like
update sometable set column1 = coalesce(?, column1), colum2 = coalesce(?, column2)
Then when the value should not be updated, use either PreparedStatement.setNull with an appropriate java.sql.Types value or a PreparedStatement.setXXX of the appropriate type with a null as value.
As discussed in the comments, an alternative if you do need to update to null, is to use a custom function with a sentinel value (either for updating to null or for using the current value). Something like:
update sometable set column1 = conditional_update(?, column1), colum2 = conditional_update(?, column2)
Where conditional_update would be something like (using Firebird 3 PSQL syntax):
create function conditional_update(new_value varchar(500), original_value varchar(500))
returns varchar(500)
as
begin
if (new_value = '$$NO_UPDATE$$') then
return original_value;
else
return new_value;
end
Where using $$NO_UPDATE$$ is a sentinel value for not updating. A potential downside of this solution is the typing of columns as a string type. You always need to use string types (I'm not sure if there are databases that would supports dynamic parameters and return types in this situation).
Let me rephrase your problem and you please tell me if this is right:
You want to be able to have the update process
sometimes you only update for a specific x
sometimes you only update for a specific y
sometimes you update for specific x and y combined
Correct? If 'yes' then the next issue is implementation possibilities.
You suggested trying to put the column itself into the parameter. Even if that's possible I'd still recommend against it. The code will get confusing.
I suggest you create a java method that builds and returns the query string (or at least the 'where' clause) based on your available parameters (x, y, etc)
Your code for invoking the JDBC Prepared statement will invoke that method to get a query String.
You will still benefit from using prepared statements. The cost is that your database will be caching several different statements instead of one, but I imagine that is a minimal issue.
You can think of auxiliar "?" variable for each column which will manage if the column should be updated or not.
update table
set x = case when 0 = ? then x else ? end,
y = case when 0 = ? then y else ? end
where etc;
Passing 0 for each 0 = ? will not update the column whereas passing 1 will update it to the value you specified.

How to implement Lookup Tables?

I am unable to grasp the concept of the lookup table.
I am currently working on a project wherein I am using two tables.
The first table consists of two columns- name(varchar) and value(varchar).
The second table also has two rows- Result(varchar) and value(varchar).
Result is used to store the values which are obtained from a Java code. Whenever the Result of the Java code matches the name in the first table, I need to update the second table with the corresponding value in the first table.
Does using lookup table help in any way? If it does, can it be explained with an example?If not, is there any other way?
Just imagine a table person with a column GenderIsMale BIT. You can set this value to 1 (yes, it is a boy) or to 0 (no, a girl). This was easy in earlier days.
Now we have more categories. According to this link facebook offers more than 50 differing categories...
There the lookup-table comes into play: You create a table which has - as minium - a unique key and a value. In most cases this is an ID INT IDENTITY and a Content VARCHAR(100) NOT NULL. You can add more columns like Abbreviation or any other additional content (e.g. other languages or codes of external code systems read about mapping tables also) directly bound to this value.
The next step is, to take the GenderIsMale-column away and replace it with a
GenderID INT NOT NULL
CONSTRAINT FK_Person_GenderID FOREIGN KEY REFERENCES GenderLookUpTable(GenderID)
The person table will store the GenderID only, the related values are stored in the side table and can be looked up.
The simple lookup table is the basic construct of how to create a relational database model in min. 3.NF or BCNF (which should be a minium reuqirement for professional database design).
Whenever the Result of the Java code matches the name in the first
table, I need to update the second table with the corresponding value
in the first table.
That's a perfect use case for database trigger, which can be used to perform various things when a change (insert, update, delete) happens in a table.
Assuming you're inserting the value of your Java calculations to your (result, value) table (let's call it foo, and the other table is bar), you can write a trigger that replaces the value being written with the value from the other table. Example given for Postgres, if using another db refer to your particular RDBMS manual to see the syntax.
CREATE FUNCTION get_value_from_lookup_table() RETURNS trigger AS $$
BEGIN
IF EXISTS (SELECT 1 FROM bar WHERE name = NEW.result) THEN
RETURN SELECT name, value FROM bar WHERE name = NEW.result;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER lookup_value
INSTEAD OF INSERT ON foo
FOR EACH ROW
EXECUTE PROCEDURE get_value_from_lookup_table();
Every time an INSERT is done on foo, a check is done to see if a row exists in bar where name=result. If so, that row is inserted, otherwise the insert goes on normally. That's the basic gist of it. The actual solution depends on table constraints, whether you need to handle inserts and updates, etc.

Decode in SQL vs. If... Else in Java

I'm looking for a solution to a simple scenario. I need to check if a value is present in a table, and if present I need Y else N
I can do it in two ways, either fetch the count of rows from the database, and code the logic in java, or use DECODE(COUNT(*),0,'N','Y')
Which is better? Is there any advantage of one over the other? Or more specifically, is there any disadvantage of using DECODE() instead of doing it in Java?
The database I have is DB2.
You should use exists. I would tend to do this as:
select (case when exists (select 1 from . . . .)
then 'Y' else 'N'
end) as flag
from sysibm.sysdummy1;
The reason you want to use exists is because it is faster. When you use count(*), the SQL engine has to process all the (appropriate) data to get the count. With exists, it can stop at the first one.
The reason to prefer case over decode() is that the former is ANSI standard SQL, available in basically all databases.
It shouldn't be any considerable difference between those 2 ways that you mentioned.
1) The DECODE will be simple and the IF will be simple.
2) You will be receiving an Int32 versus a CHAR(1) - which is not a significant difference.
So, I would consider another aspect: Which of those 2 will make your code more CLEAR?
And one more thing: if this is the ONLY thing that you're selecting on that query, you could try something like:
SELECT 'Y' FROM DUAL WHERE EXISTS (SELECT 1 FROM YOURTABLE WHERE YOURCONDITION = 1); --Oracle SQL - but should be fairly easy to translate it to DB2
This is an option to not make the DB count for every occurrence of your condition just to check if it exists.
Aggregated functions like count can be optimized with MQT - Materilized Query Tables
https://www.ibm.com/developerworks/data/library/techarticle/dm-0509melnyk/
connect to sample
alter table employee add unique (empno)
alter table department add unique (deptno)
create table count_emp_dpto_1 as (select d.deptno, e.empno, count(*) from employee e, department d where d.deptno = 1 and e.workdept = d.deptno) data initially deferred refresh immediate
set integrity for count_emp_dpto_1 immediate checked not incremental
select * from count_emp_dpto_1
connect reset

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.

Categories