SQL Server queries case sensitivity - sql

I have this database:
abcDEF
ABCdef
abcdef
if I write: select * from MyTbl where A='ABCdef'
how to get: ABCdef
and how to get:
abcDEF
ABCdef
abcdef
Thanks in advance
forgot to write - sqlCE

You can make your query case sensitive by making use of the COLLATE keyword.
SELECT A
FROM MyTbl
WHERE A COLLATE Latin1_General_CS_AS = 'ABCdef'

If you have abcDEF, ABCdef, abcdef already in the database then it's already case sensitive or you have no constraint.
You'd have to add a COLLATE on both sides to make sure it's truly case sensitive (for a non case sensitive database) which will invalidate index usage
SELECT TheColumn
FROM MyTable
WHERE TheColumn COLLATE Latin1_General_CS_AS = 'ABCdef' COLLATE Latin1_General_CS_AS
What about accents too? Latin1_General_CS_AI, Latin1_General_Bin?

Try this just add binary keyword after where:
select * from MyTbl where binary A = 'ABCdef';

It's all about collation. Each one has a suffix (CI and CS, meaning Case Insensitive, and Case Sensitive).
http://www.databasejournal.com/features/mssql/article.php/10894_3302341_2/SQL-Server-and-Collation.htm

SQL is non-case-sensitive by default, so you will get all three items if doing a simple string comparison. To make it case-sensitive, you can cast the value of the field and your search value as varbinary:
SELECT * FROM MyTbl WHERE CAST(A AS varbinary(20)) = CAST('ABCdef' as varbinary(20))
The above assumes your varchar field is sized at 20. For nvarchar double it (thanks #ps2goat).

Related

Two Where conditions on same column

There are several status an the status table. I want query like that.
select * from command where status <> 's' and status<> 'sc'
But query retrieve data with 'Status' S.
What was the issue on that?
Is the status in the DB S or s?
Try
select * from command where lower(status) NOT IN ('s', 'sc')
Just try it.. No need to check lower or caps. It searches all letter (not case sensitive).
select * from command where status NOT IN ('s', 'sc')
If you want to add condition with case sensitive, then you have to use like this..
select * from command where status COLLATE Latin1_General_CS_AS NOT IN ('s', 'sc')
The checks Col <> 's' depends on the collation of the columns. If the collation is case insensitive, then 'S' = 's' and your checks will not return S. If your collation is case sensitive which I believe is the case, will return S.
For example note the following two collations Latin1_General_CI_AS_KS_WS and Latin1_General_CS_AS_KS_WS. Note the difference in case CI and CS.
SELECT 'S' WHERE 'S' <> 's' COLLATE Latin1_General_CI_AS_KS_WS
Does not return anything
SELECT 'S' WHERE 'S' <> 's' COLLATE Latin1_General_CS_AS_KS_WS
Returns S
Coming back to your query. If this case insensitive check is a one time thing you can either as suggested by other answers do a UPPER(Col) / LOWER(Col) or use COL COLLATE Latin1_General_CI_AS_KS_WS.
If all comparisons should be case insensitive, I would suggest changing the collation of the column itself.

PostgreSQL Sort

I have a sort problem in PostgreSQL with below data:
name
-----
#CF
#CG
CD
CE
I used select name from table order by name, the result as below:
name
-----
CD
CE
#CF
#CE
It seems that Postgres just ignores the special character # and sorts the left string. However, I'd like it sorted like this:
name
-----
#CF
#CG
CD
CE
Searching the internet didn't help. I hope someone here could give a suggestion.
Use PostgreSQL's collation support to tell it you want a particular collation.
Given:
CREATE TABLE t AS VALUES ('CD'),('CE'),('#CF'),('#CE');
You can force byte-wise collation using:
SELECT * FROM t ORDER BY column1 COLLATE "C";
The "C" collation is a byte-wise collation that ignores national language rules, encoding, etc.
Just add that to the order by clause:
ORDER BY CASE WHEN LEFT(name,1) = '#' THEN 0 ELSE 1 END ASC, name ASC
Your undisclosed collation setting obviously ignores the # character for sort order. Either switch to another collation as suggested by #Craig. Or, if you want to stick to your collation for the rest of the string, add a special case for leading #.
In Postgres you can order by boolean values directly. Default order is FALSE, TRUE, NULL.
ORDER BY name !~~ '#%', name
!~~ being the Postgres shorthand for NOT LIKE.
Use this:
SELECT name
FROM table
ORDER BY name WHEN LEFT(name, 1) = '#'
THEN 0 ELSE 1 END, name

SQL Server sort order with nonprintable characters

I have a scalar value function that returns a varchar of data containing the ASCII unit seperator Char(31). I am using this result as part of an Order By clause and attempting to sort in ascending order.
My scalar value function returns results like the following (nonprintable character spelled out for reference)
ABC
ABC (CHAR(31)) DEF
ABC (CHAR(31)) DEF (CHAR(31)) HIJ
I would expect that when I order by ascending the results would be the following:
ABC
ABCDEF
ABCDEFHIJ
instead I am seeing the results as the complete opposite:
ABCDEFHIJ
ABCDEF
ABC
Now I am fairly certain that this has to do with the non-printable characters, but I am not sure why. Any idea as to why that is the case?
Thanks
The sortorder can be influenced by your COLLATION settings. Following script, explicitly using Latin1_General_CI_AS as collation orders the items as you would expect.
;WITH q (Col) AS (
SELECT 'ABC' UNION ALL
SELECT 'ABC' + CHAR(31) + 'DEF' UNION ALL
SELECT 'ABC' + CHAR(31) + 'DEF' + CHAR(31) + 'HIJ'
)
SELECT *
FROM q
ORDER BY
Col COLLATE Latin1_General_CI_AS
What collation are you using? You can verify your current database collation settings with
SELECT DATABASEPROPERTYEX('master', 'Collation') SQLCollation;
I am able to duplicate this behavior in SQL Server 2008 R2 with collation set to SQL_Latin1_General_CP1_CI_AS.
If you cannot change your collation settings, set the field to nvarchar instead of varchar. This solved the issue for me.

Flatten national characters in SQL Server

I have a column that contains pet names with national characters. How do I write the query to match them all in one condition?
|PetName|
Ćin
ćin
Ĉin
ĉin
Ċin
ċin
Čin
čin
sth like FLATTEN funciton here:
...WHERE LOWER(FLATTEN(PetName)) = 'cin'
Tried to cast it to from NVARCHAR to VARCHAR but it didn't help. I'd like to avoid using REPLACE for every character.
this should work because cyrillic collation base cases all diacritics like Đ,Ž,Ć,Č,Š,etc...
declare #t table(PetName nvarchar(100))
insert into #t
SELECT N'Ćin' union all
SELECT N'ćin' union all
SELECT N'Ĉin' union all
SELECT N'ĉin' union all
SELECT N'Ċin' union all
SELECT N'ċin' union all
SELECT N'Čin' union all
SELECT N'čin'
SELECT *
FROM #t
WHERE lower(PetName) = 'cin' COLLATE Cyrillic_General_CS_AI
You can change the collation used for the comparison:
WHERE PetName COLLATE Cyrillic_General_CI_AI = 'cin'
There isn't really a way or built-in function that will strip accents from characters.
If you are doing comparisons (LIKE, IN, PATINDEX etc), you can just force COLLATE if the column/db is not already accent insensitive.
Normally, a query like this
with test(col) as (
select 'Ćin' union all
select 'ćin')
select * from test
where col='cin'
will return both columns, since the default collation (unless you change it) is insensitive. This won't work for FULLTEXT indexes though.

how to select * from tableA where columnA values don't start with letter 'F'

Can I have a SQL query to get the data from columna in tableA whose values don't start with 'f' ?
For example:
select * from tableA where columnA
where values don't start with letter 'F'.
For a MSSQL Scenario, you should be able to use the "NOT" operator in conjunction with the LIKE operator. So your SQL would look roughly like
select * from tableA where columnA NOT LIKE 'F%'
#Evan: the statement about SQL Server being case insensitive is actually not entirely true. Case sensitivity depends on collation. The server has a collation (chosen on install), a database has a collation (chosen on DB creation) and text columns have a collation (chosen when creating the column). When no collation is specified on DB creation, the server collation will be the default. When no collation specified on column creation it gets the same collation as the DB.
But in most cases, people (luckily) install their server using a case insensitive collation, such as Latin1_General_CI_AS. CI = case insensitive, AS = accent sensitive.
On SQL Server, if I needed to get both the small f and capital F, I would go for:
where columnA NOT LIKE 'F%' and columnA NOT LIKE 'f%'
PS: I'm adding this as "answer" because I don't see any option to comment on an existing answer - I'm still new here... If anyone has an explanation why I don't get this option, don't hesitate to contact me.
Regards, Valentino.
SELECT columnA
FROM tableA
WHERE SUBSTR(columnA,1,1) <> 'f'
If you need both 'f' and 'F':
SELECT columnA
FROM tableA
WHERE SUBSTR(columnA,1,1) NOT IN ('f','F')
Going off of Lerxst's example, some DBMSs will also let you do fun stuff like this:
SELECT columnA
FROM tableA
WHERE columnA NOT LIKE ALL ('f%','F%')
I like all of the ideas above, but I usually take a different approach.
SELECT *
FROM tableA
WHERE LEFT(columnA,1) <> 'F'
T-SQL really offers a million ways to skin a cat.
Searching for both F and f seems like way too much work
SELECT *
FROM tableA
WHERE upper(substr(columnA,1,1)) != 'F'
Or to quote my friend Ritchie - when searching in sql, trim it and then force it upper