sql strictly equals, is there something? [duplicate] - sql

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
SQL server ignore case in a where expression
basically I need to check something like this
select * from users where name = #name, pass = #pass
the problem is that 'pass' = 'pAsS'
is there something more strict for string comparison in sql (ms sql-server)

It's down to your collation, which it would seem is case insensitive. For example, the standard collation is Latin1_General_CI_AS, where the CI means case insensitive. You can force a different collaction for a different comparison:
select *
from users
where name = #name
and pass COLLATE Latin1_General_CS_AS = #pass COLLATE Latin1_General_CS_AS
Incidentally, you shouldn't be storing passwords in your database - you should be salting and hashing them.

As several others have already posted you can use collations in your query or change the collation of your "pass" column to be case sensitive. You may also change your query to use the VARBINARY type instead of changing collation:
SELECT * FROM users
WHERE name = #name
AND pass = #pass
AND CAST(pass AS VARBINARY(50)) = CAST(#pass AS VARBINARY(50))
Note that I left in the pass = #pass clause. Leaving this line in the query allows SQL Server to use any index on the pass column.

You need to use a case sensitive collation for the comparison:
SELECT * FROM users
WHERE name = #name, pass = #pass
COLLATE SQL_Latin1_General_Cp1_CS_AS
See this article for more details.

It's all to do with database collation.
This should help you:
select * from users where name = #name, pass = #pass COLLATE SQL_Latin1_General_CP1_CS_AS
There is some information here regarding collations in SQL Server

For case sensitive you need to specify the collation in your query. Something like:
select * from users where name = #name, pass = #pass COLLATE SQL_Latin1_General_Cp1_CS_AS

Use a binary collation to ensure an exact match.
WHERE pass = #pass COLLATE Latin1_General_BIN

Related

SQl select statement whitespace issue

Values in SQL are USERNAME=ADMIN PASSWORD=ADMIN
SELECT * FROM TBL_USER
WHERE USERNAME='ADMIN'
AND PASSWORD COLLATE LATIN1_GENERAL_CS_AS=N'ADMIN'
The above query works fine.
2) If I add a space in front of the password.
SELECT * FROM TBL_USER
WHERE USERNAME='ADMIN'
AND PASSWORD COLLATE LATIN1_GENERAL_CS_AS=N' ADMIN'
This is also correct as it returns a message saying incorrect password.
3) If I add a space in to the end of the password:
SELECT * FROM TBL_USER
WHERE USERNAME='ADMIN'
AND PASSWORD COLLATE LATIN1_GENERAL_CS_AS=N'ADMIN '
This query should fail but it doesn't it retrieves data.
Can anyone help me in this.The third condition should fail since the value in table is 'admin' and the value provided is 'admin ' (with whitespaces at end).
Instead of using = operator use LIKE (without % wildcard)
SELECT * FROM TBL_USER WHERE USERNAME='ADMIN'
AND PASSWORD COLLATE LATIN1_GENERAL_CS_AS LIKE N'ADMIN '
And here's why: SQL WHERE clause matching values with trailing spaces
This is the expected behaviour of trailing spaces
SQL Server follows the ANSI/ISO SQL-92 specification (Section 8.2,
, General rules #3) on how to compare strings
with spaces. The ANSI standard requires padding for the character
strings used in comparisons so that their lengths match before
comparing them. The padding directly affects the semantics of WHERE
and HAVING clause predicates and other Transact-SQL string
comparisons. For example, Transact-SQL considers the strings 'abc' and
'abc ' to be equivalent for most comparison operations.
The only exception to this rule is the LIKE predicate. When the right
side of a LIKE predicate expression features a value with a trailing
space, SQL Server does not pad the two values to the same length
before the comparison occurs. Because the purpose of the LIKE
predicate, by definition, is to facilitate pattern searches rather
than simple string equality tests, this does not violate the section
of the ANSI SQL-92 specification mentioned earlier.
I suggest you add another condition to your where clause:
And DATALENGTH(Password) = DATALENGTH(N'ADMIN ')
This will add another check to ensure the input value length is the same as the Database value.
Full example:
Declare #tblUser table
(
Username nvarchar(50),
Password nvarchar(50)
)
Insert into #tblUser
Values (N'ADMIN',N'ADMIN')
select *
From #tblUser
Where Username = N'ADMIN'
And Password Collate LATIN1_GENERAL_CS_AS = N'ADMIN'
select *
From #tblUser
Where Username = N'ADMIN'
And Password Collate LATIN1_GENERAL_CS_AS = N' ADMIN'
select *
From #tblUser
Where Username = N'ADMIN'
And Password Collate LATIN1_GENERAL_CS_AS = N'ADMIN '
And DATALENGTH(Password) = DATALENGTH(N'ADMIN ')
This will work for you
SELECT * FROM TBL_USER
WHERE USERNAME='ADMIN' AND PASSWORD COLLATE LATIN1_GENERAL_CS_AS=N'ADMIN ' And LEN(PASSWORD) = LEN(Replace('admin ', ' ' , '_'))
As it will fail if the user uses spaces at the end of the password.
You can use trim function
SELECT * FROM TBL_USER WHERE USERNAME=trim('ADMIN') AND PASSWORD COLLATE LATIN1_GENERAL_CS_AS=N trim('ADMIN')
You can do a right trim in your check.
SELECT * FROM TBL_USER
WHERE USERNAME='ADMIN' AND PASSWORD COLLATE LATIN1_GENERAL_CS_AS=RTRIM(N'ADMIN ')

compare s, t with ş, ţ in SQL Server

I followed this post How do I perform an accent insensitive compare (e with è, é, ê and ë) in SQL Server? but it doesn't help me with " ş ", " ţ " characters.
This doesn't return anything if the city name is " iaşi " :
SELECT *
FROM City
WHERE Name COLLATE Latin1_general_CI_AI LIKE '%iasi%' COLLATE Latin1_general_CI_AI
This also doesn't return anything if the city name is " iaşi " (notice the foreign ş in the LIKE pattern):
SELECT *
FROM City
WHERE Name COLLATE Latin1_general_CI_AI LIKE '%iaşi%' COLLATE Latin1_general_CI_AI
I'm using SQL Server Management Studio 2012.
My database and column collation is "Latin1_General_CI_AI", column type is nvarchar.
How can I make it work?
The characters you've specified aren't part of the Latin1 codepage, so they can't ever be compared in any other way than ordinal in Latin1_General_CI_AI. In fact, I assume that they don't really work at all in the given collation.
If you're only using one collation, simply use the correct collation (for example, if your data is turkish, use Turkish_CI_AI). If your data is from many different languages, you have to use unicode, and the proper collation.
However, there's an additional issue. In languages like Romanian or Turkish, ş is not an accented s, but rather a completely separate character - see http://collation-charts.org/mssql/mssql.0418.1250.Romanian_CI_AI.html. Contrast with eg. š which is an accented form of s.
If you really need ş to equal s, you have replace the original character manually.
Also, when you're using unicode columns (nvarchar and the bunch), make sure you're also using unicode literals, ie. use N'%iasi%' rather than '%iasi%'.
In SQL Server 2008 collations versioned 100 were introduced.
Collation Latin1_General_100_CI_AI seems to do what you want.
The following should work:
SELECT * FROM City WHERE Name LIKE '%iasi%' COLLATE Latin1_General_100_CI_AI
Not tidiest solution I guess, but if you know that it's just the "ş" and "ţ" characters that are the problem, would it be acceptable to do a replace?
SELECT *
FROM City
WHERE replace(replace(Name,'ş','s'),'ţ','t') LIKE COLLATE Latin1_general_CI_AI '%iasi%' COLLATE Latin1_general_CI_AI
You just need to change collation of name field before like operation. Check test code below
DECLARE #city TABLE ( NAME NVARCHAR(20) )
INSERT INTO #city
VALUES ( N'iaşi' )
SELECT *
FROM #city
WHERE name LIKE 'iasi'
--No return
SELECT *
FROM #city
WHERE name COLLATE Latin1_general_CI_AI LIKE '%iasi%'
--Return 1 row
This problem was haunting me for some time, until now, when I've finally figured it out.
Presuming your table or column is of SQL_Latin1_General_CP1_CI_AS collation, if you do:
update
set myCol = replace(myCol , N'ș', N's')
from MyTable
and
update
set myCol = replace(myCol,N'ț',N't')
from MyTable
the replace function will not find these characters, because the "ș" made from your keyboard (Romanian Standard keyboard) differs from the "ş" or "ţ" found in your database.
As a comparison: ţț and şș - you can see that they differ because the accents are closer to the "s" or "t" character.
Instead, you must do:
update
set myCol = replace(myCol , N'ş', N's')
from MyTable
and
update
set myCol = replace(myCol,N'ţ',N't')
from MyTable

How to find values in all caps in SQL Server?

How can I find column values that are in all caps? Like LastName = 'SMITH' instead of 'Smith'
Here is what I was trying...
SELECT *
FROM MyTable
WHERE FirstName = UPPER(FirstName)
You can force case sensitive collation;
select * from T
where fld = upper(fld) collate SQL_Latin1_General_CP1_CS_AS
Try
SELECT *
FROM MyTable
WHERE FirstName = UPPER(FirstName) COLLATE SQL_Latin1_General_CP1_CS_AS
This collation allows case sensitive comparisons.
If you want to change the collation of your database so you don't need to specifiy a case-sensitive collation in your queries you need to do the following (from MSDN):
1) Make sure you have all the information or scripts needed to re-create your user databases and all the objects in them.
2) Export all your data using a tool such as the bcp Utility.
3) Drop all the user databases.
4) Rebuild the master database specifying the new collation in the SQLCOLLATION property of the setup command. For example:
Setup /QUIET /ACTION=REBUILDDATABASE /INSTANCENAME=InstanceName
/SQLSYSADMINACCOUNTS=accounts /[ SAPWD= StrongPassword ]
/SQLCOLLATION=CollationName
5) Create all the databases and all the objects in them.
6) Import all your data.
You need to use a server collation which is case sensitive like so:
SELECT *
FROM MyTable
WHERE FirstName = UPPER(FirstName) Collate SQL_Latin1_General_CP1_CS_AS
Be default, SQL comparisons are case-insensitive.
Try
SELECT *
FROM MyTable
WHERE FirstName = LOWER(FirstName)
Could you try using this as your where clause?
WHERE PATINDEX(FirstName + '%',UPPER(FirstName)) = 1
Have a look here
Seems you have a few options
cast the string to VARBINARY(length)
use COLLATE to specify a case-sensitive collation
calculate the BINARY_CHECKSUM() of the strings to compare
change the table column’s COLLATION property
use computed columns (implicit calculation of VARBINARY)
Try This
SELECT *
FROM MyTable
WHERE UPPER(FirstName) COLLATE Latin1_General_CS_AS = FirstName COLLATE Latin1_General_CS_AS
You can find good example in Case Sensitive Search: Fetching lowercase or uppercase string on SQL Server
I created a simple UDF for that:
create function dbo.fnIsStringAllUppercase(#input nvarchar(max)) returns bit
as
begin
if (ISNUMERIC(#input) = 0 AND RTRIM(LTRIM(#input)) > '' AND #input = UPPER(#input COLLATE Latin1_General_CS_AS))
return 1;
return 0;
end
Then you can easily use it on any column in the WHERE clause.
To use the OP example:
SELECT *
FROM MyTable
WHERE dbo.fnIsStringAllUppercase(FirstName) = 1
Simple way to answer this question is to use collation. Let me try to explain:
SELECT *
FROM MyTable
WHERE FirstName COLLATE SQL_Latin1_General_CP1_CI_AS='SMITH’
In the above query I have used collate and didn’t use any in built sql functions like ‘UPPER’. Reason because using inbuilt functions has it’s own impact.
Please find the link to understand better:
performance impact of upper and collate

Changing Case of Strings (Lower to Upper) in SQL Server

I have 2 databases, one with lowercase data and another with uppercase data.
DECLARE #NAME VARCHAR(40)
SELECT #NAME = UPPER(SELECT NAME FROM DELETED)
By executing SELECT NAME FROM DELETED, I am selecting data that is lower case.
By executing SELECT #NAME = UPPER(SELECT NAME FROM DELETED), I would want to select uppercase data on the query inside the UPPER().
Question is can I use the UPPER() with the SELECT, like the query above?
How about
SELECT UPPER(NAME) FROM DELETED
instead of
UPPER(SELECT NAME FROM DELETED)
You'll need an extra pair of brackets
Select #NAME = UPPER((SELECT NAME FROM DELETED));
(Not that I'd do it that way, see Lukas's answer for a better approach).
Use
SELECT #pNAME = UPPER([NAME]) FROM DELETED

SQL Server check case-sensitivity?

How can I check to see if a database in SQL Server is case-sensitive? I have previously been running the query:
SELECT CASE WHEN 'A' = 'a' THEN 'NOT CASE SENSITIVE' ELSE 'CASE SENSITIVE' END
But I am looking for other ways as this has actually given me issues in the past.
Edit - A little more info:
An existing product has many pre-written stored procedures. In a stored procedure #test != #TEST depending on the sensitivity of the server itself. So what I'm looking for is the best way to check the server for its sensitivity.
Collation can be set at various levels:
Server
Database
Column
So you could have a Case Sensitive Column in a Case Insensitive database. I have not yet come across a situation where a business case could be made for case sensitivity of a single column of data, but I suppose there could be.
Check Server Collation
SELECT SERVERPROPERTY('COLLATION')
Check Database Collation
SELECT DATABASEPROPERTYEX('AdventureWorks', 'Collation') SQLCollation;
Check Column Collation
select table_name, column_name, collation_name
from INFORMATION_SCHEMA.COLUMNS
where table_name = #table_name
If you installed SQL Server with the default collation options, you might find that the following queries return the same results:
CREATE TABLE mytable
(
mycolumn VARCHAR(10)
)
GO
SET NOCOUNT ON
INSERT mytable VALUES('Case')
GO
SELECT mycolumn FROM mytable WHERE mycolumn='Case'
SELECT mycolumn FROM mytable WHERE mycolumn='caSE'
SELECT mycolumn FROM mytable WHERE mycolumn='case'
You can alter your query by forcing collation at the column level:
SELECT myColumn FROM myTable
WHERE myColumn COLLATE Latin1_General_CS_AS = 'caSE'
SELECT myColumn FROM myTable
WHERE myColumn COLLATE Latin1_General_CS_AS = 'case'
SELECT myColumn FROM myTable
WHERE myColumn COLLATE Latin1_General_CS_AS = 'Case'
-- if myColumn has an index, you will likely benefit by adding
-- AND myColumn = 'case'
SELECT DATABASEPROPERTYEX('<database name>', 'Collation')
As changing this setting can impact applications and SQL queries, I would isolate this test first. From SQL Server 2000, you can easily run an ALTER TABLE statement to change the sort order of a specific column, forcing it to be case sensitive. First, execute the following query to determine what you need to change it back to:
EXEC sp_help 'mytable'
The second recordset should contain the following information, in a default scenario:
Column_Name Collation
mycolumn SQL_Latin1_General_CP1_CI_AS
Whatever the 'Collation' column returns, you now know what you need to change it back to after you make the following change, which will force case sensitivity:
ALTER TABLE mytable
ALTER COLUMN mycolumn VARCHAR(10)
COLLATE Latin1_General_CS_AS
GO
SELECT mycolumn FROM mytable WHERE mycolumn='Case'
SELECT mycolumn FROM mytable WHERE mycolumn='caSE'
SELECT mycolumn FROM mytable WHERE mycolumn='case'
If this screws things up, you can change it back, simply by issuing a new ALTER TABLE statement (be sure to replace my COLLATE identifier with the one you found previously):
ALTER TABLE mytable
ALTER COLUMN mycolumn VARCHAR(10)
COLLATE SQL_Latin1_General_CP1_CI_AS
If you are stuck with SQL Server 7.0, you can try this workaround, which might be a little more of a performance hit (you should only get a result for the FIRST match):
SELECT mycolumn FROM mytable WHERE
mycolumn = 'case' AND
CAST(mycolumn AS VARBINARY(10)) = CAST('Case' AS VARBINARY(10))
SELECT mycolumn FROM mytable WHERE
mycolumn = 'case' AND
CAST(mycolumn AS VARBINARY(10)) = CAST('caSE' AS VARBINARY(10))
SELECT mycolumn FROM mytable WHERE
mycolumn = 'case' AND
CAST(mycolumn AS VARBINARY(10)) = CAST('case' AS VARBINARY(10))
-- if myColumn has an index, you will likely benefit by adding
-- AND myColumn = 'case'
SQL server determines case sensitivity by COLLATION.
COLLATION can be set at various levels.
Server-level
Database-level
Column-level
Expression-level
Here is the MSDN reference.
One can check the COLLATION at each level as mentioned in Raj More's answer.
Check Server Collation
SELECT SERVERPROPERTY('COLLATION')
Check Database Collation
SELECT DATABASEPROPERTYEX('AdventureWorks', 'Collation') SQLCollation;
Check Column Collation
select table_name, column_name, collation_name
from INFORMATION_SCHEMA.COLUMNS
where table_name = #table_name
Check Expression Collation
For expression level COLLATION you need to look at the expression. :)
It would be generally at the end of the expression as in below example.
SELECT name FROM customer ORDER BY name COLLATE Latin1_General_CS_AI;
Collation Description
For getting description of each COLLATION value try this.
SELECT * FROM fn_helpcollations()
And you should see something like this.
You can always put a WHERE clause to filter and see description only for your COLLATION.
You can find a list of collations here.
You're interested in the collation. You could build something based on this snippet:
SELECT DATABASEPROPERTYEX('master', 'Collation');
Update
Based on your edit — If #test and #TEST can ever refer to two different variables, it's not SQL Server. If you see problems where the same variable is not equal to itself, check if that variable is NULL, because NULL = NULL returns `false.
The best way to work with already created tables is that,
Go to Sql Server Query Editor
Type: sp_help <tablename>
This will show table's structure , see the details for the desired field under COLLATE column.
then type in the query like :
SELECT myColumn FROM myTable
WHERE myColumn COLLATE SQL_Latin1_General_CP1_CI_AS = 'Case'
It could be different character schema <SQL_Latin1_General_CP1_CI_AS>, so better to find out the exact schema that has been used against that column.
How can I check to see if a database in SQL Server is case-sensitive?
You can use below query that returns your informed database is case sensitive or not or is in binary sort(with null result):
;WITH collations AS (
SELECT
name,
CASE
WHEN description like '%case-insensitive%' THEN 0
WHEN description like '%case-sensitive%' THEN 1
END isCaseSensitive
FROM
sys.fn_helpcollations()
)
SELECT *
FROM collations
WHERE name = CONVERT(varchar, DATABASEPROPERTYEX('yourDatabaseName','collation'));
For more read this MSDN information ;).
SQL Server is not case sensitive. SELECT * FROM SomeTable is the same as SeLeCT * frOM soMetaBLe.