Mysql collation error on laravel query, related to search parameter - mysql

My search query has COLLATE utf8mb4_bin which is necessary to differentiate between european characters and non-european character, for example a vs ä.
If I run the query with hard coded search term, it works in phpmyadmin, and it works on this fiddle: db-fiddle. You can see that the table has CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci.
But on this other fiddle site ( sqlfiddle), the same query gives the error:
COLLATION 'utf8mb4_bin' is not valid for CHARACTER SET 'utf8'
And in laravel, if I run the query with hard coded search term, it works without error, but if I use a parameter I get this error:
SQLSTATE[42000]: Syntax error or access violation: 1253 COLLATION 'utf8mb4_bin' is not
valid for CHARACTER SET 'binary'
So it is very strange. Here is the laravel query with bound parameters which produces the above error:
$query_events = "SELECT e.id, e.title, e.location,e.event_at, e.content as content,
e.limited_participants,e.max_participants,associations.name,
CONCAT(:url,'/events/', e.id) AS permalink,
(SELECT COUNT(*) FROM event_participants evp WHERE evp.event_id = e.id)
AS participants
FROM events AS e
LEFT JOIN associations ON e.association_id = associations.id
WHERE CONCAT(e.title ,e.location ,e.content ,associations.name )
LIKE :search
COLLATE utf8mb4_bin
ORDER BY e.event_at
DESC
LIMIT 5";
$results['events'] = DB::select($query_events,[
'url' => $url,
'search' => '%' . $search . '%'
]);
If I remove COLLATE utf8mb4_bin, there is no error but european/non-eurpoean letters are mixed up in the search results. If I hard code some search parameter (like in the fiddles) and comment out the 'search' property in the array, the query works as it should, giving the right results.
I use xampp and the mysql version is 5.7.22 according to phpmyadmin.
So I need to use that collation and need to be able to use a search parameter, but how do I avoid this error??

Plan A: Preface the query with
SET NAMES utf8mb4;
Plan B: change the CHARACTER SET of the literal:
LIKE _utf8mb4"%oteborg%"

Related

Case-sensitive string comparison in SQL (MariaDB, MySQL)

I have read many questions and answers on StackOverflow (posted years ago) concerning this issue, but none that I found have worked using a 10.3.22-MariaDB server and libmysql - 5.6.43 as database client.
I am trying to do the following:
SELECT * FROM table WHERE 'column' = 'data' LIMIT 1
The command above, however, will select the row both if the value of column is DaTa or data and I am endeavouring to go for the latter only.
Answers to similar questions from 2011 (MySQL) suggest:
SELECT * FROM table WHERE BINARY 'column' = 'data'
SELECT * FROM table WHERE 'column' = BINARY 'data'
SELECT * FROM table WHERE 'column' LIKE BINARY 'data'
SELECT * FROM table WHERE 'column' LIKE 'data' COLLATE latin1_general_cs
None of the commands above respected the case of the letters. Moreover, the last one did not even run due to
Unrecognized keyword. (near "COLLATE" at position 45)
Unexpected token. (near "latin1_general_cs" at position 53)
What is the solution to this problem in 2020? What am I doing wrong or what is wrong with my server?
Any help would be highly appreciated!
This should work:
WHERE BINARY column = 'data'
However, it will not work if you put column in single quotes. That would be a string as opposed to a column reference.
This works without the single quotes around cloumn
SELECT * FROM table1 WHERE `column` LIKE 'data' COLLATE latin1_general_ci;
As you asked the collation has to fir to the character set, so if you have like me utf8mb5, you write:
SELECT * FROM table1 WHERE `column` LIKE _latin1 'data' COLLATE latin1_general_ci;

MySQL query: search multiple strings in a single field, from CSV in other field/table?

I have a table that contains two TEXT fields with textual content, and in a separate table, a field that contains comma separate values of keywords that can be more than one word. The following query works in my WAMP using Appserv, does not works in our Hostgator LAMP...why??
SELECT
t.content_me, t.content_visitor, t.Id, exp.owner_user_id, exp.name
FROM (SELECT t.content_me, t.content_visitor
FROM `texts` AS t
WHERE t.owner_user_id=1 *<== obviously this changes...*
ORDER BY t.Id DESC) AS t
INNER JOIN exp ON t.Id = exp.owner_user_id AND
t.content_me REGEXP (REPLACE(exp.keywords,',','|'))
WHERE t.owner_user_id=e.owner_user_id=6
ORDER BY t.Id DESC
Furthermore, if I literally put a value in this part:
t.content_me REGEXP (REPLACE(exp.keywords,',','|'))
as lets say:
t.content_me REGEXP ('yeah|ok')
It works in Hostgator. So I guess the problem is that REGEXP (REPLACE(exp.keywords,',','|')) thingy...right?
EDIT
Ok, I simplified the query just for the fun of it :)
SELECT
t.Id, t.text, t.owner_user_id FROM `t`
LEFT JOIN e ON e.owner_user_id = t.owner_user_id
WHERE
t.text REGEXP REPLACE(e.keywords,',','|') AND t.owner_user_id=1
Same results: works in WAMP, doesn't in LAMP. Also if I do literal REGEXP like
REGEXP REPLACE('yeah,can',',','|')
Works in both servers. My guess is that something is happening with
REGEXP REPLACE(e.keywords,',','|')
i.e, having the REGEXP use field content and not literal sting.
EDIT:
Well...now I see the LAMP MySQL throws an error (not happening in WAMP):
Illegal mix of collations (utf8_general_ci,IMPLICIT) and (utf8_unicode_ci,IMPLICIT) for operation 'regexp'
So....
REGEXP REPLACE(e.keywords,',','|') COLLATE utf8_unicode_ci
Fixed it

matching exactly word in utf8 in where clause mysql

I have a query like this :
SELECT * FROM category_keyword WHERE keyword = 'cho'
This query is return result keyword ={ cho , chợ , chờ , chợ ...}. I only want the result is keyword = 'cho' ( not 'chợ, chờ ...') . How can I do?
The collation of table is utf8_unicode_ci
With utf8 collation, cho does equal chờ. If you want to compare as binary:
SELECT * FROM category_keyword WHERE keyword = CONVERT('cho' USING binary)
Change the collation for the column to utf8_bin. This is better than using CONVERT because it allows the use of an index. However, if you sometimes need utf8_bin (exact match) and sometimes need utf8_unicode_ci (for case folding and accent stripping), you are out of luck, performance-wise.

MySQL DB selects records with and without umlauts. e.g: '.. where something = FÖÖ'

My Table collation is "utf8_general_ci". If i run a query like:
SELECT * FROM mytable WHERE myfield = "FÖÖ"
i get results where:
... myfield = "FÖÖ"
... myfield = "FOO"
is this the default for "utf8_general_ci"?
What collation should i use to only get records where myfield = "FÖÖ"?
SELECT * FROM table WHERE some_field LIKE ('%ö%' COLLATE utf8_bin)
A list of the collations offered by MySQL for Unicode character sets can be found here:
http://dev.mysql.com/doc/refman/5.0/en/charset-unicode-sets.html
If you want to go all-out and require strings to be absolutely identical in order to test as equal, you can use utf8_bin (the binary collation). Otherwise, you may need to do some experimentation with the different collations on offer.
For scandinavian letters you can use utf8_swedish_ci fir example.
Here is the character grouping for utf8_swedish_ci. It shows which characters are interpreted as the same.
http://collation-charts.org/mysql60/mysql604.utf8_swedish_ci.html
Here's the directory listing for other collations. I'm no sure which is the used utf8_general_ci though. http://collation-charts.org/mysql60/

MySQL Collate Latin1_General_CI_AI Problem

I have the following select statement where I'm trying to search for a players first and last name that may contain accents in it.
$sql = "
SELECT * FROM player
WHERE player.player_first LIKE '%$first%'
AND player.player_last LIKE '%$last%'
";
I adding COLLATE Latin1_General_CI_AI after before both of the LIKE clauses, but that didn't work and returned errors.
Any help would be appreciated.
According to MySQL doc the collation Latin1_General_CI_AI does not exists.
Try latin1_general_ci instead.