Select string which contains - java

This is a very simplified version of what i'm working on but hopefully it will get my point across.
I have a mysql table which looks something like this:
CREATE TABLE Table1(
ID INT AUTO_INCREMENT,
Val VARCHAR(50),
PRIMARY KEY (id)
);
INSERT INTO Table1 (Val) SELECT "Reference.Int('ABCD')";
INSERT INTO Table1 (Val) SELECT "Reference.Str('EFG','ABC')";
INSERT INTO Table1 (Val) SELECT "Reference.Int('HIJ','EFG','ABC')";
The method i'm working on receives as parameter one of the values in the brackets, for example: "EFG". Is it possible for me to grab all the rows in the table which contain this value. I am aware that if i do something like:
SELECT * from Table1 where Val LIKE "%EFG%"
i can get the right values, my problem is that i need to be more specific because for example one of the values can look something like :
Reference.Int('ABCD') + EFGX/200
or
EFG + anything else
Meaning that i need to somehow include this parts also: "Reference.Str()". I don't really care about anything else that is in the brackets, my only concern is to get the ones which contain the value of the parameter i receive.
I was wondering if this could be solved by using REGEXP, but my knowledge of this is weak at best.
Any help is appreciated.

You can use regexp, but there's no need. Just include the quotes surrounding your values in the search term:
select ...
where val like '%\'EFG\'%'

I don't think this is a good fit for a SQL query. You're probably best off creating a second table that stores tokens found in strings, and a reference back to the parent record.
So you could do something like
select record_id from tokens where token_val = 'EFG';
and then
select * from records where record_id in (*results from pervious query)
Basically the idea is to do the hard work up front, ONCE per record, rather than trying to parse on the fly on every query.

Try this:
SELECT * FROM Table1 WHERE Val LIKE "Reference.Str(%'EFG'%"
SQL FIDDLE DEMO

I think you could use SUBSTRING_INDEX to get only the part of the strings between brackets:
SUBSTRING_INDEX(SUBSTRING_INDEX(Val, "(", -1), ")", 1)
and then you can use FIND_IN_SET:
SELECT *
FROM Table1
WHERE
FIND_IN_SET(
'\'EFG\'',
SUBSTRING_INDEX(SUBSTRING_INDEX(Val, "(", -1), ")", 1)
)
See it here.

Related

How to add the result of a query into a column

I have the following query which returns a column of values:
SELECT CONCAT(
from_unixtime(lastSaleTime/1000, '%Y-%d-%m %h:%i:%s.'),
CAST(EXTRACT(MICROSECOND FROM from_unixtime(lastSaleTime/1000))/1000
AS SIGNED)
) FROM IEX_Tick;
How can I copy this column to an existing column in the same table?
I believe a subquery would do:
UPDATE IEX_Tick SET SomeColumn = (
SELECT CONCAT(
from_unixtime(lastSaleTime/1000, '%Y-%d-%m %h:%i:%s.'),
CAST(EXTRACT(MICROSECOND FROM from_unixtime(lastSaleTime/1000))/1000 AS SIGNED)
) FROM IEX_Tick;
)
Edit:
(in response to this comment)
After doing some research, I found that, even though the suggested solution above is valid SQL, it's not a supported way of updating a table in MySQL.
Information I gathered from various related posts here on Stack Overflow (such as this and this) suggests that MySQL restricts these types of UPDATE queries:
... because your update could be cyclical… what if updating that record causes something to happen which made the WHERE condition FALSE? You know that isn’t the case, but the engine doesn’t. There also could be opposing locks on the table in the operation.
Therefore, a viable alternative that helps avoid this arbitrary restriction set by MySQL is to use another subquery, this time in your FROM clause, as shown below:
UPDATE IEX_Tick SET SomeColumn = (
SELECT CONCAT(
from_unixtime(lastSaleTime/1000, '%Y-%d-%m %h:%i:%s.'),
CAST(EXTRACT(MICROSECOND FROM from_unixtime(lastSaleTime/1000))/1000 AS SIGNED)
) FROM (
SELECT * FROM IEX_Tick AS SomeName
);
)
Note: I would personally avoid using the SELECT * FROM IEX_Tick, especially if IEX_Tick has many columns. I good way to optimise the subquery would be to use only the column(s) needed.

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 make a primary key start with a specific letter?

Here I am using MySQL and I want my primary key to start with a letter, like D000. Then everytime I enter a new record the primary key auto increments like so:
D001
D002
D003.
How can I do this?
You can't AUTO_INCREMENT a column whose type is VARCHAR.
What you could do is make it BIGINT and AUTO_INCREMENT, and whenever you need it as String, you can prepend it with your letter 'D' like:
Long dbKey = ...;
String key = "D" + dbKey;
You could create a stored procedure for this to set an "auto-incremented" string as the default value for this column, but it just doesn't worth the hassle. Plus working with numbers is always faster and more efficient than working with strings.
I'm not sure whether I get your question right, but shouldn't the following work?
CREATE TRIGGER myTrigger
BEFORE INSERT
ON myTable
FOR EACH ROW
BEGIN
SET NEW.myCustomId = COALESCE('D', RPAD('0',3,NEW.id));
END
for this case you NEED a "normal" primary key column..
Two ideas.
(Useless IMHO) I think Maria DB has virtual columns, though MySQL I think not. But you have views. So you could make a normal INT, AUTOINCREMENT and in the view have a calculated column concatting your key.
One can use different number ranges for different tables.
ALTER TABLE debtors AUTO_INCREMENT=10000;
ALTER TABLE creditors AUTO_INCREMENT=30000;
ALTER TABLE guests AUTO_INCREMENT=50000;
This admittedly is a lame solution, but might do. I think such a distinction might be what you are aiming at.
Not sure why you need it but you can add the D AFTER you fetched the data (String id = "D" + autoIncId;).
You can't insert a string or anything in an autoincrement field and I can't see anyway this can be useful (all the recorde will have a D, so no one has).
If you want to declare a row default, you can add a boolean column named DEFAULT.
while(rs.next()){
String id = rs.getBoolean("DEFAULT")?"D":"ND";
id+=rs.getLong(1);
}
EDIT
As per your comment I understand that you want to select the max ID and add 1 to it. Then it's ok to use an autoincrement field in your DB and it must be a number type (INTEGER, BIGINT...).
Please FORGET to add the "D" to your primary key, it will simply not going to work as you want. The autoincrement takes the last inserted ID and adds 1 to it. If your last id is "D3" adding 1 has the same meaning as adding 4 to "apple". You are using different types.
There is no way for SQL or any other programming language to understand that if you add 1 to "D3" it should become "D4". What you need to do is get rid of that D (which purpose I still don't understand).
Yo may try to do this aberration at your own risk:
INSERT INTO table (id, a, b, c)
VALUES ( fn_get_key( LAST_INSERT_ID("table_name ") +1), "a", "b", "c");
Where fn_get_key is a function that will convert the number into your desired string AND will execute:
ALTER TABLE table_name AUTO_INCREMENT = start_value;
Anyway I do not recommend your approach. Numeric strings are faster and easier to sort. You could always create a view that transforms the ID or use logic o change from the "D001" key to "1". Foreing key and uniqness of ids enforcement will be harder and more expensive

JOOQ How to select the min 'id' from a table

In mysql I want to execute a query like this
SELECT MIN(id) FROM table;
The more I read about JOOQ syntax and the aggregate functions, the confused I get.
I thought something like this would work
select( EVENT.EVENTID , min() ).from( EVENT ).fetch();
or
Result<Integer> er = context.select( EVENT.EVENTID.min()).fetch();
I tried a work around by selecting the whole first record
Result<EventRecord> er2 = context.selectFrom(EVENT).orderBy(EVENT.EVENTID.asc()).limit(1).fetch();
If the result has size 0, a record does not exist, but when it is not 0 I get the right record. I would like to use the min() function but can't get the syntax right.
The query you want to write in SQL is this one:
SELECT MIN(event.eventid) FROM event
This is why your two attempts didn't work
// 1. You cannot combine single columns with aggregate functions in SQL,
// unless you're grouping by those columns
// 2. You didn't pass any cargument column to the MIN() function
context.select( EVENT.EVENTID , min() ).from( EVENT ).fetch();
// 3. This doesn't specify any FROM clause, so your database won't know what
// table you want to select the MIN(eventid) from
context.select( EVENT.EVENTID.min()).fetch();
Note that these thoughts are not specific to jOOQ, they are related to SQL in general. When using jOOQ, always think of the SQL statement you want to express first (the one at the top of my answer). So your jOOQ statement would look like any of these:
// "Postfix notation" for MIN()
context.select(EVENT.EVENTID.min()).from(EVENT).fetch();
// "Prefix notation" for MIN(), where min() is static-imported from
// org.jooq.impl.DSL
context.select(min(EVENT.EVENTID)).from(EVENT).fetch();
It looks like the fetchAny() method will return the record with the first/lowest record id.
EventRecord record = context.selectFrom(EVENT).fetchAny();
As #LukasEder mentioned there are many alternative methods, and he may be generous and follow up on some of those. Thanks Lucas

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.

Categories