accent insensitive mysql search with PDO - php

I am trying to make an accent insensitive search using collate. But it doesn't work. Furthermore, I heard that my code below might not be optimal if my database becomes really large. Thus, any ideas on how to make this code efficient even for large databases is highly appreciated as well.
<?php
$search_FirstName="%".$_POST['First_Name']."%";
$search_LastName="%".$_POST['Last_Name']."%";
$search_Email="%".$_POST['Email']."%";
$stmt = $con->prepare('SELECT * FROM persons WHERE FirstName LIKE ? collate utf8_general_ci AND LastName LIKE ? collate utf8_general_ci AND Email LIKE ? collate utf8_general_ci');
$stmt->execute([$search_FirstName,$search_LastName,$search_Email]);
?>

I think that you can directly change the collation of your database to latin1_swedish_ci.
And after you could directly write your request like that :
$stmt = $con->prepare('SELECT * FROM persons WHERE FirstName LIKE ? AND LastName LIKE ? AND Email LIKE ?');

Related

Special characters sensitive sql query [duplicate]

I have a MySQL table with utf8 general ci collation. In the table, I can see two entries:
abad
abád
I am using a query that looks like this:
SELECT * FROM `words` WHERE `word` = 'abád'
The query result gives both words:
abad
abád
Is there a way to indicate that I only want MySQL to find the accented word? I want the query to only return
abád
I have also tried this query:
SELECT * FROM `words` WHERE BINARY `word` = 'abád'
It gives me no results. Thank you for the help.
If your searches on that field are always going to be accent-sensitive, then declare the collation of the field as utf8_bin (that'll compare for equality the utf8-encoded bytes) or use a language specific collation that distinguish between the accented and un-accented characters.
col_name varchar(10) collate utf8_bin
If searches are normally accent-insensitive, but you want to make an exception for this search, try;
WHERE col_name = 'abád' collate utf8_bin
Update for MySQL 8.0, plus addressing some of the Comments and other Answers:
The CHARACTER SET matches the beginning of the COLLATION.
Any COLLATION name ending in _bin will ignore both upper/lower case and accents. Examples: latin1_bin, utf8mb4_bin.
Any COLLATION name containing _as_ will ignore accents, but do case folding or not based on _ci vs _cs.
To see the collations available (on any version), do SHOW COLLATION;.
utf8mb4 is now the default charset. You should be using that instead of utf8.
It is better to have the CHARACTER SET and COLLATION set 'properly' on each column (or defaulted by the table definition) than to dynamically use any conversion routine such as CONVERT().
In my version (MySql 5.0), there is not available any utf8 charset collate for case insensitive, accent sensitive searches. The only accent sensitive collate for utf8 is utf8_bin. However it is also case sensitive.
My work around has been to use something like this:
SELECT * FROM `words` WHERE LOWER(column) = LOWER('aBád') COLLATE utf8_bin
Accepted answer is good, but beware that you may have to use COLLATE utf8mb4_bin instead!
WHERE col_name = 'abád' collate utf8mb4_bin
Above fixes errors like:
MySQL said: Documentation 1253 - COLLATION 'utf8_bin' is not valid for
CHARACTER SET 'utf8mb4'
The MySQL bug, for future reference, is http://bugs.mysql.com/bug.php?id=19567.
Check to see if the database table collation type end with "_ci", This stands for case insensitive...
Change it to collation the same or nearest name without the "_ci" ...
For example... change "utf8_general_ci" to "utf8_bin"
Mke
I was getting the same error.
I've changed the collation of my table to utf8_bin (through phpMyAdmin) and the problem was solved.
SELECT * FROM `words` WHERE column = 'abád' collate latin1_General_CS
(or your collation including cs)
You can try searching for the hex variable of the character, HEX() within mysql and use a similar function within your programming language and match these. This worked well for me when i was doing a listing where a person could select the first letter of a person.
Well, you just described what utf8_general_ci collation is all about (a, á, à, â, ä, å all equals to a in comparison).
There have also been changes in MySQL server 5.1 in regards to utf8_general_ci and utf8_unicode_ci so it's server version dependent too. Better check the docs.
So, If it's MySQL server 5.0 I'd go for utf8_unicode_ci instead of utf8_general_ci which is obviously wrong for your use-case.
That works for me for an accent insensitive and case insensitive search in MySql server 5.1 in a database in utf8_general_ci, where column is a LONGBLOB.
select * from words where '%word%' LIKE column collate utf8_unicode_ci
with
select * from words where'%word%' LIKE column collate utf8_general_ci
the result is case sensitive but not accent sensitive.

SQL query that is insensitive towards non-latin characters?

Is there any way I can write a select query with where clause, that ignores non-latin characters?
For example there is Lithuanian character Ė, obviously the equivalent in latin character would be E. So is there anyway I can write a query like this:
SELECT * FROM `table` WHERE `keyword` LIKE %E%;
And I want it to return all records that contain any of these characters: E,Ė,Ę, is there any way I can achieve this automatically with SQL (or even in PHP level)?
You don't say what you've tried. You also don't say what character set (utf-8) and collation your table contains. Those are the ways you control those things by default.
You could try this:
SELECT * FROM `table` WHERE `keyword` COLLATE utf8_general_ci LIKE %E%
Or this
SELECT * FROM `table` WHERE `keyword` COLLATE utf8_lithuanian_ci LIKE %E%
I don't know if the second one will work for what you want, because I don't know Lithuanian. Are E, Ė, and Ę considered the same letter in the dictionary? If they are not, then the Lithuanian collation won't match them to each other.
If you do find that a particular collation works, you can alter your column to use that collation by default.
alter table `table`
change `keyword` `keyword` collate utf8_lithuanian_ci
That's a good idea because then you have a chance of indexes speeding your search.

Uppercase is not respected in PHP/MySQL

I have a problem with PHP and MySQL:
An user with account:
username: StAr
password: 4LasK4
Can login with:
username: star
password: 4lask4
Uppercases are not respected.
What may be the problem?
Thanks
The collation determines whether two strings are equal. You should change the collation for the username and password columns to case sensitive or binary. For example:
alter table TableName modify username varchar(xx) collate utf8_bin,
modify password varchar(xx) collate utf8_bin;
Check out the column definition and make sure your collation is not case insensitive (ci). You can try with this:
alter table your_table modify username varchar(xx) collate utf8_bin
Many MySQL installations have a default collation setting of utf8_general_ci. This makes these two operations yield precisely the same result.
SELECT * from users WHERE name = 'StAr'
SELECT * from users WHERE name = 'star'
You can try ALTERing the collation for your name column in your database. Or you can use a query like this:
SELECT * from users WHERE name = 'StAr' COLLATE utf8_bin
This utf8_bin collation compares for precise equality. If you put the COLLATE in your query, however, you may disable the use of an index for the query and cause MySQL performance trouble.

Character Case Problems

So I have my login form in my website.
And for example my username is JuvarAbrera (saved in mysql).
When I try to login using this username ---> juvarabrera
It is still logged-in in my website. Now, I want it NOT to logged-in because of the the J and A are uppercased.
So, how can I do that? I think I explained it very well.
Thanks. :)
You can collate the value in the query:
SELECT `id` FROM `users` WHERE `username` = 'php_value' COLLATE utf8_general_cs
Change column collation to utf8_bin (i.e. when using utf8_general_ci)
Take care of *_general_* collations because comparisions base on language rules. So have a look
in utf8_general_ci the following is true: 'a'='A', 'ä'='A'
in utf8_general_cs the following is true: 'Ä'='A'
in utf8_bin none of these is true, and I think that's what you want
The following SQL query will allow for upper-cased names:
SELECT *
FROM login
WHERE uname = '$username' AND
BINARY(uname) = BINARY('$username')

not case sensitive query in mysql

i need to query my database and find results :
mysql_query("select * from ".ALU_TABLE." where username like '%$q%' or name like '%$q%'");
if i have a name in my table such as Book and i enter book in search box it wont show the Book
i need to query my database as not to be case sensitive.
You can use the LOWER() function
... WHERE LOWER(username) LIKE blabl OR LOWER(name) LIKE asdasd
You need to append something like COLLATE utf8_general_ci to your query. (The _ci suffix stands for case insensitive.)
Have a look at the documentation: 9.1.7.1. Using COLLATE in SQL Statements:
With the COLLATE clause, you can override whatever the default collation is for a comparison. COLLATE may be used in various parts of SQL statements.

Categories