The correct way to do this is to let the database handle the case sensitivity. In order to do that you have to change the collation
of the field username
or password
(it depends of their current collation).
All you have to do is to change the collation of the field username
to a collation whose name ends with _ci
(it stands for case insensitive
) and the collation of the field password
to a collation whose name ends with _cs
(from case sensitive
).
The actual names of the collations depend on the character set of your table.
For example, this is the definition of a table that uses latin1
as a charset:
CREATE TABLE `users` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(32) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`password` varchar(32) CHARACTER SET latin1 COLLATE latin1_general_cs DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
If you change the collation you don't need to worry about the case sensitivity of the values any more and you don't need to change the queries.
Sample code using the table above
mysql> INSERT INTO `users` (`username`, `password`)
-> VALUES ('John Doe', 'passwd1'), ('john doe', 'PASSWD1');
Query OK, 2 rows affected (0.00 sec)
mysql> SELECT * FROM `users` WHERE `username` = 'JOHN DOE';
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | John Doe | passwd1 |
| 2 | john doe | PASSWD1 |
+----+----------+----------+
2 rows in set (0.00 sec)
mysql> SELECT * FROM `users` WHERE `password` = 'passwd1';
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | John Doe | passwd1 |
+----+----------+----------+
1 row in set (0.00 sec)
Alternative solution, using the excellent suggestion of @spencer7593
You don't need to change the collation of the fields (it is recommended but if you cannot do it then this is an alternative solution). You can force the collation you want in the query:
Force case sensitive comparison of username
:
mysql> SELECT * FROM `users` WHERE `username` COLLATE latin1_general_cs = 'john doe';
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 2 | john doe | PASSWD1 |
+----+----------+----------+
1 row in set (0.00 sec)
Force case insensitive comparison of password
:
mysql> SELECT * FROM `users` WHERE `password` COLLATE latin1_general_ci = 'passwd1';
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | John Doe | passwd1 |
| 2 | john doe | PASSWD1 |
+----+----------+----------+
2 rows in set (0.00 sec)