MYSQL LIKE different behaviors for different languages, all tables utf8 - php

I have three tables each with 3 columns, they are identical to each other. Only difference is se_words created with mysql GUI and the other two are created programmatically thrue sql inside mysql GUI.
se_words
en_words
es_words
-> id, name, user
I want to find words through the last 3 chars.
SELECT * FROM `es_words` WHERE word LIKE '%nar' // returns empty results (should be at least 500-1000+)
SELECT * FROM `en_words` WHERE word LIKE '%ate' // returns empty results (should be at least 500-1000+)
SELECT * FROM `se_words` WHERE word LIKE '%ens' // returns 1000+ results
The big problem is that en_words and es_words which are utf8 (same as se_words) always returns empty result.
I have changed it to latin, utf8_bin, utf8_unicode_ci, latin_spanish_ci etc but it doesnt matter. Still gives empty result
but
if I change the sql code to just 1 char and procent sign on both sides, the code gives a result.
SELECT * FROM `es_words` WHERE word LIKE '%a%' // returns 10000+ results
SELECT * FROM `en_words` WHERE word LIKE '%a%' // returns 10000+ results
How come same sqlcode different tables returns different result when all columns has multiply values which should be returned on LIKE search?
edit
Few of the words that should be returned upon LIKE search
es_words
abadernar,abaldonar,abanar,abandonar,abarrenar
en_words
aagate,abacate,abacinate,abalienate,abbate
From the code with trimmed variables
SELECT w.id, w.word, w.user
FROM en_words AS w
WHERE w.word LIKE '%gel' ORDER BY LENGTH(word) ASC LIMIT 0,500

Looks like an \r followed from the dictonary. Could only see it through an SQL DUMP. PHP would not show it at all.
I hope it solves the problem for you in the future who encounter it
(943, 'abridgments\r', 0),
(944, 'abrikosov\r', 0),
(945, 'abrikossov\r', 0),
(946, 'abril\r', 0),
(947, 'abrim\r', 0),
(948, 'abrin\r', 0),
(949, 'abris\r', 0),
(950, 'abristle\r', 0),

Related

Comparing 2 sets of words in MYSQL

I am creating a query where in i would need to compare 2 sets of words. I need to compare a.error_description with b.KE_TAGS which both contain sets of words.
Example of text:
a.error_description = "LockResource engine call failed in script GLB_LOCK..."
b.KE_TAGS = "LockResource, GLB_LOCKRESOURCE_100_PS"
Both columns contain the word "LockResource".
Here is my Query below:
The expected result should show the KE_ID based on the KE_TAG "LockResource, GLB_LOCKRESOURCE_100_PS" for the error_description which contains "LockResource engine call failed in script GLB_LOCK..."
Select a.error_id, a.job_ID, a.error, a.error_description,
CONCAT('%',b.KE_TAGS,'%'), b.KE_TAGS, b.KE_ID
from errors_input as a right join knowledge_entry as b
on a.error_Description like CONCAT('%',b.KE_TAGS,'%') -- issue is in this line
WHERE a.error like '%BB_RAISEERROR_100_PS%'***
Hope you can help. thanks!

ID number zero, one, o and i in query

We have a system that creates a 5 digit alpha-numeric string of numbers and letters. Originally, I had the full alphabet and 0-9 so something like the following was possible:
0O1I0
Because different fonts may be used on different systems, there was confusion between the o's and i's so I updated the function to only include the numbers. Because there are historical items with the "o" and "i" items I have been asked to modify our search to automatically look for a zero if an o is entered and a 1 if an i is entered (or vice versa).
These are 5 digit ids with 2 possible values for the specific character. I'm thinking I could loop over the value with PHP prior to writing the query to build a list of options and then check if "IN (list of items)" in my query. I don't know if there's something built in that I'm missing though in MySQL like..
WHERE ID = o/0, i/1, etc.
So how about parsing the id in php, replacing every occurence of 0 or O with regex string [o0], and similarly replacing i and 1 with [i1].
Then you could use this string in your query like this
WHERE id REGEXP '...[i1]...[o0]...'
The php code could look like this
$id = '0O1I0';
$id = preg_replace('/[i1]/i', '[i1]', $id);
$id = preg_replace('/[o0]/i', '[o0]', $id);
echo $id; // [i1][o0][i1][o0][o0]
...
mysqli_query($conn, "SELECT ... WHERE id REGEXP '$id'");
What about something like
select <stuff> from <table>
where replace(replace(upper(id), 'I', '1'), 'O', '0') like '%<number-search-term>%'
EDIT (more detail)
replace() in mysql takes three arguments: the original term, what to look for, and what to swap it with. In the where clause I did a nested replace. The inner one replaced any instances of I with 1 and the outer one took the inner replace as its argument (so with all Is as 1s) and replaced any Os with 0s. This is then compared against the number search term (I used a like statement).

MySQL select only using first word of variable

I am using php and mySQL. I have a select query that is not working. My code is:
$bookquery = "SELECT * FROM my_books WHERE book_title = '$book' OR book_title_short = '$book' OR book_title_long = '$book' OR book_id = '$book'";
The code searches several title types and returns the desired reference most of the time, except when the name of the book starts with a numeral. Though rare, some of my book titles are in the form "2 Book". In such cases, the query only looks at the "2", assumes it is a "book_id" and returns the second entry in the database, instead of the entry for "2 Book". Something like "3 Book" returns the third entry and so forth. I am confused why the select is acting this way, but more importantly, I do not know how to fix it.
If you have a column in your table with a numeric data type (INT, maybe), then your search strategy is going to work strangely for values of $book that start with numbers. You have discovered this.
The following expression always returns true in SQL. It's not intuitive, but it's true.
99 = '99 Luftballon'
That's because, when you compare an integer to a string, MySQL implicitly does this:
CAST(stringvalue AS INT)
And, a cast of a string beginning with the text of an integer always returns the value of the integer. For example, the value of
CAST('99 Luftballon' AS INT)
is 99. So you'll get book id 99 if you look for that search term.
It's pointless to try to compare an INT column to a text string that doesn't start with an integer, because CAST('blah blah blah' AS INT) always returns zero. To make your search strategy work better, you should consider omitting OR book_id = '$book' from your search query unless you know that the entirety of $book is a number.
As others mention, my PHP allowed both numerical enties and text entries from the browser. My query was then having a hard time with this, interpreting some of my text entries as numbers by truncating the end. Thus, my "2 Book" was being interpreted as the number "2" and then being queried to find the second book in the database. To fix this I just created a simple if statement in PHP so that my queries only looked for text or numbers. Thus, in my case, my solution was:
if(is_numeric($book)){
$bookquery = "SELECT * FROM books WHERE book_id = '$book'";
}else{
$bookquery = "SELECT * FROM books WHERE book_title = '$book' OR book_title_short = '$book' OR book_title_long = '$book'";
}
This is working great and I am on my way coding happily again. Thanks #OllieJones and others for your questions and ideas which helped me see I needed to approach the problem differently.
Not sure if this is the correct answer for you but it seems like you are searching for only exact values in your select. Have you thought of trying a more generic search for your criteria? Such as...
$bookquery = "SELECT * FROM my_books WHERE book_title LIKE '".$book."' OR book_title_short LIKE '".$book."' OR book_title_long LIKE '".$book."' OR book_id LIKE '".$book."'"
If you are doing some kind of searching you might even want to ensure the characters before the search key are found as well like so....
$bookquery = "SELECT * FROM my_books WHERE book_title LIKE '%".$book."' OR book_title_short LIKE '%".$book."' OR book_title_long LIKE '%".$book."' OR book_id LIKE '%".$book."'"
The % is a special char that looks for allows you to search for the chars you want to search for PLUS any characters before this that aren't in the search criteri... for example $book = "any" with a % before hand in the query like so, '%".$book."'"`` would return bothcompanyand also the wordany` by itself.
If you need to you can add a % to the end also like so, `'%".$book."%'"`` and it would do the same for the beginning and end of the search key

MYSQL LIKE categories returning wrong query due to %

I have a CMS with a bunch of different tags and categories. I obviously use each category as a unique ID and save them in the database like so:
cats -> 2,15,115
tags -> 13,33,113
That is a simple example.
I am having problems when I want to show related content by a GET variable $cat to use in my query:
WHERE cats LIKE '%$cat%'
Here is the challenge, if the $cat = '5' , then it returns, 5, 15, 55, 115... and so on. I just need it to match just '5' and nothing else!
I'm sure I am missing something really, really simple.
EDIT:
The find_in_set works really well. However, my other challenge is my $GET variable is sometimes like this: $cat = 150,181
So how can I use the variable $cat to see if there is just one of those matches ? I want to match either 150 OR 181 against the query ?
you can use FIND_IN_SET() since column cats has these values 2,15,115
SELECT * FROM tableName WHERE FIND_IN_SET('5', cats) > 0
MySQL FIND_IN_SET
If you use LIKE with wildcard character '%' you extend your search all values containing '5' in base of you put your %.
%value% (cointaining)
%value (end with value)
value% (start with value)
You can use like as equal, simply not used %, but I advice you to use equal operator (=)

MySQL "LIKE" search doesn't work

I've imported a .txt database in MySQL through "LOAD DATA INFILE", and everything seemed working, the only problem is that if I search a record on the DB with the following query:
"SELECT * FROM hobby WHERE name LIKE 'Beading'"
it returns 0 rows, while if I use
""SELECT * FROM hobby WHERE name LIKE '%Beading%'"
it returns 1 row, even if exist one record with name=Beading. Does anybody know what could it depend on?
When using SQL LIKE:
You should use a wildcard identifier such as (or not):
'%word' - return results that the value ends with the letters: "word".
'word%' - return results that begin with the letters: "word".
%word% - return results that include the letters: "word" anywhere.
there are some more pattern search combination like:
'abc' LIKE 'abc' true
'abc' LIKE 'a%' true
'abc' LIKE 'b' true
'abc' LIKE 'c' false
If you want an exact match you should use:
"SELECT * FROM hobby WHERE name='Beading'"
But LIKE 'Beading' should also work, so it's probably a spaces issue or case sensitivity problem.
You need to take care of collation case (sensitivity) when you want to make sure your results are complete.
Say your table is UTF...CS and you want to make an insensitive case search you should declare it in your SQL query, for example:
SELECT * FROM hobby WHERE name COLLATE UTF8_GENERAL_CI LIKE 'beading'
try testing different approaches and see what fits your goal best.
the first one doesnt work because Like statment you should use '%search word%'
you should use this one
"SELECT * FROM hobby WHERE name LIKE '% Beading %' or name LIKE '% Beading'
or name LIKE 'Beading %' or name LIKE 'Beading'"

Categories