How do I perform a case-sensitive search using LIKE? - sql-server-2008

I'm trying to find records that contain a string of 6 or more alpha-numeric characters in uppercase. Some examples:
PENDING 3RDPARTY CODE27
I'm using the following statement:
SELECT Details
FROM MyTable
WHERE Details LIKE '%[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]%';
This is returning all records that contain any 6-or-more-letter word, regardless of case.
I've added a COLLATE statement:
SELECT Details
FROM MyTable
WHERE Details COLLATE Latin1_General_CS_AS LIKE '%[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]%';
This changes nothing. It still returns records with 6-or-more-letter word, regardless of case.
Just as a test, I tried:
SELECT Details
FROM MyTable
WHERE Details COLLATE Latin1_General_CS_AS LIKE '%pending%';
SELECT Details
FROM MyTable
WHERE Details COLLATE Latin1_General_CS_AS LIKE '%PENDING%';
Both of these worked, returning records containing "pending" and "PENDING" respectively. So the issue seems to by the LIKE claus's pattern matching.
What can I do to perform this case-sensitive search?

Try using COLLATE Latin1_General_BIN rather than COLLATE Latin1_General_CS_AS

Update due to #GeraldSv: Use collation Latin1_General_BIN
SELECT Details
FROM MyTable
WHERE Details
LIKE '%[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]%'
COLLATE Latin1_General_BIN;
You need to place the collation specifier after the string to be matched rather than the column:
SELECT Details
FROM MyTable
WHERE Details
LIKE '%[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]%'
COLLATE Latin1_General_CS_AS;
Update: While my answer above is correct, there is a bug filed at Connect: Case-SENSITIVITY doesn't work when using a range in like with COLLATE Latin1_General_CS_AS which Microsoft have marked as 'By Design".
I verified by using AdventureWorks2008R2 (case insensitive, out of the box default), in the Person.Person table I changed 3 last names ending in 'n' to 'N', and then ran the following queries:
SELECT COUNT(*)
FROM Person.Person
WHERE LastName LIKE '%N' COLLATE Latin1_General_CS_AS
Success. Return 3 rows as expected.
SELECT COUNT(*)
FROM Person.Person
WHERE LastName LIKE '%[N]' COLLATE Latin1_General_CS_AS
Success. Return 3 rows as expected.
SELECT COUNT(*)
FROM Person.Person
WHERE LastName LIKE '%[N-N]' COLLATE Latin1_General_CS_AS
Success. Return 3 rows as expected.
SELECT COUNT(*)
FROM Person.Person
WHERE LastName LIKE '%[M-N]' COLLATE Latin1_General_CS_AS
Fails. Returns 3334 Rows (which is all Lastname's ending in 'n' and 'N')
Update: Thanks to #GeraldSv, this works:
SELECT COUNT(*)
FROM Person.Person
WHERE LastName LIKE '%[M-N]' COLLATE Latin1_General_BIN

I use the following:
SELECT COUNT(*)
FROM Person.Person
WHERE LastName COLLATE Latin1_General_CS_AS != upper(LastName) COLLATE Latin1_General_CS_AS

Related

mysql query to select user count with Like clause

I have a forum, there's an option for user to change their names. Also i have staff members with names like [ADM]James. I want to prevent users to change his name in James.
Example: I have a memeber from staff with name [ADM]James, users should not be able to change his name in simply James.
There's my query : SELECT COUNT(*) FROM users WHERE name='James' LIKE '[%%' However this query return strange numbers it always return whole count of users.
What i do wrong?
EDIT, WHAT IS UNCLEAR?
I have 2 staff members. Admins and moderators, admins have tag name [ADM] moderators [MOD]. Example two names: [ADM]James [MOD]Jeff .. When a user try to change his name in James count should return 1. Because there is already one staff memeber with name [ADM]James.
CREATE TABLE `user` (
`id` int(0) NOT NULL AUTO_INCREMENT,
`user` varchar(24) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT 'NONAME',
) ENGINE = MyISAM AUTO_INCREMENT = 191782 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;
Use below query,
SELECT COUNT(*) FROM users WHERE name LIKE '%]%'
SELECT user, COUNT(*) FROM users WHERE name LIKE '%[ADM]%' group by user;
SELECT COUNT(*) FROM users WHERE name LIKE '%James%'
Will count every name that has 'James' on it.
WHERE name='James' LIKE '[%%' is not a valid where clause
The syntax of the LIKE operator is expr LIKE pat [ESCAPE 'escape_char']
You can either use % or _
% matches any number of characters, even zero characters.
_ matches exactly one character.

MySQL magic column "name" and synthesized columns

So I got a SQL statement. The idea is that I want to do a case-insensitive LIKE.
I do it like this:
SELECT
FilenameId AS id,
LOWER(CONVERT(BINARY(Filename.Name) USING utf8)) AS name
FROM Filename
WHERE name LIKE '%something%'
COLLATE utf8_general_ci
This works fine, however my query also returns the case-transformed name. What I want to do
is synthesize the insensitive name and do a LIKE query on it, but also return the non case-transformed name.
SELECT
FilenameId AS id,
Filename.Name AS name,
LOWER(CONVERT(BINARY(Filename.Name) USING utf8)) AS iname
FROM Filename
WHERE iname LIKE '%something%'
COLLATE utf8_general_ci
...but then MySQL happily refuses:
Unknown column 'iname' in 'where clause'
What am I doing wrong? I am on MySQL 5.5 FWIW.
I don't know why you came up with this, but usually others have trouble getting LIKE case sensitive, not the other way round.
Write your query simply like this:
SELECT
FilenameId AS id,
Filename.Name AS name
FROM Filename
WHERE name LIKE '%something%'
And in general, you can't access aliases in WHERE clause. Either put your query into a subquery like Dhinakaran suggested or use HAVING (if you are lazy).
The difference? WHERE is rowbased, HAVING works on the result after applying WHERE clause (and GROUP BY).
From the manual:
The following two statements illustrate that string comparisons are not case sensitive unless one of the operands is a binary string:
mysql> SELECT 'abc' LIKE 'ABC';
-> 1
mysql> SELECT 'abc' LIKE BINARY 'ABC';
-> 0
Create a sub query then put where on subquery
Select * from (SELECT
FilenameId AS id,
Filename.Name AS name,
LOWER(CONVERT(BINARY(Filename.Name) USING utf8)) AS iname
FROM Filename ) temp
WHERE temp.iname LIKE '%something%'
COLLATE utf8_general_ci
Or
SELECT
FilenameId AS id,
Filename.Name AS name,
AS iname
FROM Filename
WHERE LOWER(CONVERT(BINARY(Filename.Name) USING utf8)) LIKE '%something%'
COLLATE utf8_general_ci

MySQL Where Query using string with special characters

I have the following query:
SELECT *
FROM (
`teams`
)
WHERE `name` = 'mi equiñerolico'
And the result of this query is:
idteam|name|datet
9|mi equiñerolíco|2012-06-23 12:15:32
As you can see it retrieves a row with the name 'mi equiñerolíco' even though that my Where clause establish that it must be 'mi equiñerolico'.
teams table has utf8_general_ci collation.
How can I solve this ambiguity?
You could use a binary collation to force an accent-sensitve compare:
select *
from teams
where name = 'mi equiñerolico' collate utf8_bin

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.

MySQL detect capitalization?

I want to do a query via phpmyadmin in which I can find any entries for Lastname that are not capitalized. Can I do that purely with sql?
If not: is there an easy way with php, or do I have to write code starting with substring()? Thanks.
Something like this should work
SELECT lastname
FROM tbl
WHERE CONCAT( UPPER( SUBSTRING( lastname, 1, 1 ) ) ,
LOWER( SUBSTRING( lastname FROM 2 ) ) ) != lastname Collate latin1_german2_cs;
The left side creates a proper-cased lastname, and compares it against the column case sensitively (using _cs collation)
According to MySQL doc, you could try:
SELECT * FROM your_table
WHERE your_field COLLATE <your_collation> REGEXP '[[:lower:]]+';
-- <your_collation> being a case sensitive collation,
-- such as latin1_general_cs, or utf8_bin, depending on your_table collation