SQL query to search for lowercase strings - sql

I want a SQL query which can search for a certain word, but only in lowercase.
I am trying
select * from employees where name like LOWER('%smith%')however, this does not bring back any results.
However, when I do
select * from employees where name like '%smith%' it returns employees with name SMITH and smith....in my case i just want it to return where employee names are lower-cased.
Thanks in advance!

Your default collation is likely set to a case-insensitive option. Put simply this causes all character comparison to be performed as if the sides of the comparison are of the same case, regardless of whether this is true or not.
You may use a COLLATE statement following the column name in the WHERE clause:
select * from employees where name COLLATE Latin1_General_CS_AS like '%smith%'
However, if you have a significant need for case-sensitive comparison you may wish to change the default collation of your database as explicitly marking collation is very verbose, as you can see.

Normally, in order to query a table in a case sensitive way, you would designate the column (or the entire database) with a case sensitive collation.
For performance reasons, that will be the preferred approach if you will be regularly performing case sensitive queries against this column.
However, in a pinch, you can specify the query collation on the fly. This comes at the cost of a more expensive query plan, so regard it as a last resort.
For example:
SELECT * FROM Employees
WHERE EmployeeName COLLATE SQL_Latin1_General_CP1_CS_AS
LIKE '%smith%'
There are a variety of case sensitive collations, so you will typically want to choose the one that is closest to the standard case insensitive collation you are using.
You can check that by running these statements to check the configured collation:
--Server level
SELECT SERVERPROPERTY('COLLATION')
--Database level
SELECT DATABASEPROPERTYEX('DatabaseName', 'Collation')
--Column level
USE DatabaseName
GO
SELECT name, collation_name
FROM sys.columns
WHERE OBJECT_ID IN (SELECT OBJECT_ID
FROM sys.objects
WHERE type = 'U'
AND name = 'TableName')
AND name = 'ColumnName'
Most likely these will all return the same value. For example, SQL_Latin1_General_CP1_CI_AS, in which case the collation you would use for case sensitive queries would be SQL_Latin1_General_CP1_CS_AS.
Depending on the result you get, you will want to select the related case-sensitive collation from this list.

Use collation COLLATE Latin1_General_CP1_CS_AS to explicit Case Sensitive,
default collation when installing SQL Server is SQL_Latin1_General_CP1_CI_AS
select * from employees where name COLLATE Latin1_General_CS_AS like '%smith%'
Where
CS: Case Sensitive
AS: Accent sensitive

You can also use Binary_checksum(lower()) function as below.
select * from employees where
BINARY_CHECKSUM(EmployeeName) = BINARY_CHECKSUM(Lower(EmployeeName))
Please note: If the column Employeename has null values, it lists the nulls as well in your results.

Related

What are the consequences of changing database tables from danish_norwegian_ci_ai to danish_norwegian_ci_as?

I'm having trouble joining tables in the same database, because, for some reason, some columns are of the collation Danish_Norwegian_CI_AS and some are Danish_Norwegian_CI_AI. Most are Danish_Norwegian_CI_AS, and that's the specified collation for the database as well.
I want to alter the collation of these tables, so that they all are Danish_Norwegian_CI_AS, but I can't understand where I should begin to understand the consequences of making this change. Will some characters be mistranslated for example?
I've tried to understand the differences between collations, but can't find much. I understand that the difference has something to do with ascent sensitivity.
I expect all tables, columns etc. to be of collation Danish_Norwegian_CI_AS
The difference between AS and AI is that the sort order (or searches etc.) see or not a difference between letters with (or without) accents, e.g.
-- This query would result in 'different', as it uses an accent sensitive collation
SELECT CASE
WHEN 'ö' COLLATE Latin1_General_CI_AS = 'o' COLLATE Latin1_General_CI_AS
THEN 'same'
ELSE 'different'
END
-- This query would result in 'same', as it uses an accent insensitive collation
SELECT CASE
WHEN 'ö' COLLATE Latin1_General_CI_AI = 'o' COLLATE Latin1_General_CI_AI
THEN 'same'
ELSE 'different'
END
CS and CI are similar, it means case sensitive ore case insensitive.
Generally it is possible to use a different collation in a table or even in a column, but I never thought this a good idea, esp. when you link tables using a character field, like
SELECT
p.Matchcode,
p.Name,
i.Ammount
FROM
Persons p
INNER JOIN Invoices i ON i.Matchcode = p.Matchcode
This could cause unexpected (and wrong) results when the two tables (or the column Matchcode in the two tables) are using a different collation.
If you need a different collation in a specific query, it would be better to add the collation in the query, something like
SELECT
Lastname COLLATE Latin1_General_CS_AS AS Lastname,
Firstname COLLATE Latin1_General_CS_AS AS Firstname
FROM
Persons
Understanding COLLATE DATABASE_DEFAULT

Firebird order by collation

I am with strange problem with Firebird 2.5.
My database has default charset = utf8.
I have a column p_nname in patienten table:
CREATE TABLE PATIENTEN (
P_NNAME VARCHAR(25) DEFAULT '' NOT NULL COLLATE UNICODE_CI,
I expect collation to work everywhere. I mean in WHERE and ORDER BY clauses.
What I have is working collation in WHERE. Two queries below give me similar result and it is good.
select * from patienten where p_nname='adler'
select * from patienten where p_nname='ADler'
Problem is ORDER BY clause does not work as I expect.
This SQL works as if the column has no UNICODE_CI collation.
select * from patienten order by p_nname
To get the needed result with good sorting I have to write so:
select * from patienten order by p_nname collate unicode_ci
Is there a way to omit COLLATE flag in ORDER BY clause?
Looks like a bug indeed, the documentation states:
The keyword COLLATE specifies the collation order for a string column
if you need a collation that is different from the normal one for this
column. The normal collation order will be either the default one for
the database character set or one that has been set explicitly in the
column's definition.
so it should work without specifing the collate clause in ORDER BY. I suggest you file a bug report.

Is the LIKE operator case-sensitive with SQL Server?

In the documentation about the LIKE operator, nothing is told about the case-sensitivity of it. Is it? How to enable/disable it?
I am querying varchar(n) columns, on an Microsoft SQL Server 2005 installation, if that matters.
It is not the operator that is case sensitive, it is the column itself.
When a SQL Server installation is performed a default collation is chosen to the instance. Unless explicitly mentioned otherwise (check the collate clause bellow) when a new database is created it inherits the collation from the instance and when a new column is created it inherits the collation from the database it belongs.
A collation like sql_latin1_general_cp1_ci_as dictates how the content of the column should be treated. CI stands for case insensitive and AS stands for accent sensitive.
A complete list of collations is available at https://msdn.microsoft.com/en-us/library/ms144250(v=sql.105).aspx
(a) To check a instance collation
select serverproperty('collation')
(b) To check a database collation
select databasepropertyex('databasename', 'collation') sqlcollation
(c) To create a database using a different collation
create database exampledatabase
collate sql_latin1_general_cp1_cs_as
(d) To create a column using a different collation
create table exampletable (
examplecolumn varchar(10) collate sql_latin1_general_cp1_ci_as null
)
(e) To modify a column collation
alter table exampletable
alter column examplecolumn varchar(10) collate sql_latin1_general_cp1_ci_as null
It is possible to change a instance and database collations but it does not affect previously created objects.
It is also possible to change a column collation on the fly for string comparison, but this is highly unrecommended in a production environment because it is extremely costly.
select
column1 collate sql_latin1_general_cp1_ci_as as column1
from table1
All this talk about collation seem a bit over-complicated. Why not just use something like:
IF UPPER(##VERSION) NOT LIKE '%AZURE%'
Then your check is case insensitive whatever the collation
If you want to achieve a case sensitive search without changing the collation of the column / database / server, you can always use the COLLATE clause, e.g.
USE tempdb;
GO
CREATE TABLE dbo.foo(bar VARCHAR(32) COLLATE Latin1_General_CS_AS);
GO
INSERT dbo.foo VALUES('John'),('john');
GO
SELECT bar FROM dbo.foo
WHERE bar LIKE 'j%';
-- 1 row
SELECT bar FROM dbo.foo
WHERE bar COLLATE Latin1_General_CI_AS LIKE 'j%';
-- 2 rows
GO
DROP TABLE dbo.foo;
Works the other way, too, if your column / database / server is case sensitive and you don't want a case sensitive search, e.g.
USE tempdb;
GO
CREATE TABLE dbo.foo(bar VARCHAR(32) COLLATE Latin1_General_CI_AS);
GO
INSERT dbo.foo VALUES('John'),('john');
GO
SELECT bar FROM dbo.foo
WHERE bar LIKE 'j%';
-- 2 rows
SELECT bar FROM dbo.foo
WHERE bar COLLATE Latin1_General_CS_AS LIKE 'j%';
-- 1 row
GO
DROP TABLE dbo.foo;
You have an option to define collation order at the time of defining your table. If you define a case-sensitive order, your LIKE operator will behave in a case-sensitive way; if you define a case-insensitive collation order, the LIKE operator will ignore character case as well:
CREATE TABLE Test (
CI_Str VARCHAR(15) COLLATE Latin1_General_CI_AS -- Case-insensitive
, CS_Str VARCHAR(15) COLLATE Latin1_General_CS_AS -- Case-sensitive
);
Here is a quick demo on sqlfiddle showing the results of collation order on searches with LIKE.
The like operator takes two strings. These strings have to have compatible collations, which is explained here.
In my opinion, things then get complicated. The following query returns an error saying that the collations are incompatible:
select *
from INFORMATION_SCHEMA.TABLES
where 'abc' COLLATE SQL_Latin1_General_CP1_CI_AS like 'ABC' COLLATE SQL_Latin1_General_CP1_CS_AS
On a random machine here, the default collation is SQL_Latin1_General_CP1_CI_AS. The following query is successful, but returns no rows:
select *
from INFORMATION_SCHEMA.TABLES
where 'abc' like 'ABC' COLLATE SQL_Latin1_General_CP1_CS_AS
The values "abc" and "ABC" do not match in a case-sensitve world.
In other words, there is a difference between having no collation and using the default collation. When one side has no collation, then it is "assigned" an explicit collation from the other side.
(The results are the same when the explicit collation is on the left.)
Try running,
SELECT SERVERPROPERTY('COLLATION')
Then find out if your collation is case sensitive or not.
You can change from the property of every item.
You can easy change collation in Microsoft SQL Server Management studio.
right click table -> design.
choose your column, scroll down i column properties to Collation.
Set your sort preference by check "Case Sensitive"

How to find rows that have a value that contains a lowercase letter

I'm looking for an SQL query that gives me all rows where ColumnX contains any lowercase letter (e.g. "1234aaaa5789"). Same for uppercase.
SELECT * FROM my_table
WHERE UPPER(some_field) != some_field
This should work with funny characters like åäöøüæï. You might need to use a language-specific utf-8 collation for the table.
SELECT * FROM my_table WHERE my_column = 'my string'
COLLATE Latin1_General_CS_AS
This would make a case sensitive search.
EDIT
As stated in kouton's comment here and tormuto's comment here whosoever faces problem with the below collation
COLLATE Latin1_General_CS_AS
should first check the default collation for their SQL server, their respective database and the column in question; and pass in the default collation with the query expression. List of collations can be found here.
SELECT * FROM Yourtable
WHERE UPPER([column_NAME]) COLLATE Latin1_General_CS_AS !=[Column_NAME]
This is how I did it for utf8 encoded table and utf8_unicode_ci column, which doesn't seem to have been posted exactly:
SELECT *
FROM table
WHERE UPPER(column) != BINARY(column)
for search all rows in lowercase
SELECT *
FROM Test
WHERE col1
LIKE '%[abcdefghijklmnopqrstuvwxyz]%'
collate Latin1_General_CS_AS
Thanks Manesh Joseph
IN MS SQL server use the COLLATE clause.
SELECT Column1
FROM Table1
WHERE Column1 COLLATE Latin1_General_CS_AS = 'casesearch'
Adding COLLATE Latin1_General_CS_AS makes the search case sensitive.
Default Collation of the SQL Server installation SQL_Latin1_General_CP1_CI_AS is not case sensitive.
To change the collation of the any column for any table permanently run following query.
ALTER TABLE Table1
ALTER COLUMN Column1 VARCHAR(20)
COLLATE Latin1_General_CS_AS
To know the collation of the column for any table run following Stored Procedure.
EXEC sp_help DatabaseName
Source : SQL SERVER – Collate – Case Sensitive SQL Query Search
I've done something like this to find out the lower cases.
SELECT *
FROM YourTable
where BINARY_CHECKSUM(lower(ColumnName)) = BINARY_CHECKSUM(ColumnName)
mysql> SELECT '1234aaaa578' REGEXP '^[a-z]';
I have to add BINARY to the ColumnX, to get result as case sensitive
SELECT * FROM MyTable WHERE BINARY(ColumnX) REGEXP '^[a-z]';
I'm not an expert on MySQL I would suggest you look at REGEXP.
SELECT * FROM MyTable WHERE ColumnX REGEXP '^[a-z]';
In Posgresql you could use ~
For example you could search for all rows that have col_a with any letter in lowercase
select * from your_table where col_a '[a-z]';
You could modify the Regex expression according your needs.
Regards,
--For Sql
SELECT *
FROM tablename
WHERE tablecolumnname LIKE '%[a-z]%';
Logically speaking Rohit's solution should have worked, but it didn't. I think SQL Management Studio messed up when trying to optimize this.
But by modifying the string before comparing them I was able to get the right results. This worked for me:
SELECT [ExternalId]
FROM [EquipmentSerialsMaster] where LOWER('0'+[ExternalId]) COLLATE Latin1_General_CS_AS != '0'+[ExternalId]
This works in Firebird SQL, it should work in any SQL queries I believe, unless the underlying connection is not case sensitive.
To find records with any lower case letters:
select * from tablename where upper(fieldname) <> fieldname
To find records with any upper case letters:
select * from tablename where lower(fieldname) <> fieldname

How to change the collation of sqlite3 database to sort case insensitively?

I have a query for sqlite3 database which provides the sorted data. The data are sorted on the basis of a column which is a varchar column "Name". Now when I do the query
select * from tableNames Order by Name;
It provides the data like this.
Pen
Stapler
pencil
Means it is considering the case sensitive stuff. The way I want is as follows
Pen
pencil
Stapler
So what changes should I make in sqlite3 database for the necessary results?
Related How to set Sqlite3 to be case insensitive when string comparing?
To sort it Case insensitive you can use ORDER BY Name COLLATE NOCASE
The SQLite Datatypes documentation discusses user-defined collation sequences. Specifically you use COLLATE NOCASE to achieve your goal.
They give an example:
CREATE TABLE t1(
a, -- default collation type BINARY
b COLLATE BINARY, -- default collation type BINARY
c COLLATE REVERSE, -- default collation type REVERSE
d COLLATE NOCASE -- default collation type NOCASE
);
and note that:
-- Grouping is performed using the NOCASE collation sequence (i.e. values
-- 'abc' and 'ABC' are placed in the same group).
SELECT count(*) GROUP BY d FROM t1;
select * from tableNames Order by lower(Name);
Michael van der Westhuizen explains in his comment below why this is not a good way. I am leaving this answer up so as to preserve his comment and to serve as a warning to others who might have the same 'bright' idea I had ;-)
Use this statement in your SQLite database:
PRAGMA case_sensitive_like = false