SQL server key violation due to case insesitivity - sql-server

I m having a table in which a primary key is there with 2 columns(CODE nvarchar,VALUE nvarchar).This table contains the values in the Key columns as (X8900,A) but when I try to insert a new value as (X8900,a) ,its giving error message “primary key violation”.
Why its giving this error,if case is different for values column and is there any solution for this in order avoid the error ?

You can specify if SQL Server should be case sensitive or not using collation. In this instance the column must have a case sensitive collation in order for you to be able to specify any type of unique constraint on it. For example, the first example will fail whereas the second will work, notice the CI and CS for case insensitive and sensitive.
CREATE TABLE test1 (
col1 varchar(20) COLLATE Latin1_General_CI_AS PRIMARY KEY
)
INSERT INTO test1 VALUES ('ASD')
INSERT INTO test1 VALUES ('asd')
CREATE TABLE test2 (
col1 varchar(20) COLLATE Latin1_General_CS_AS PRIMARY KEY
)
INSERT INTO test2 VALUES ('ASD')
INSERT INTO test2 VALUES ('asd')
Collation can be set at the column or database level. If set at database level then all character columns without a collation specified adopt the database collation.

You have to check the collation of your database. If you have a case insensitive collation, 'A' == 'a'. If you need to maintain difference between cases, you can either change the collation to a case sensitive collation, or you could cast the strings to varbinary. A binary representation differentiates between cases.
Collations can be set at the server level (i.e what databases default to) and at the database level (overriding the server collation). At an even more granular level, you can set collation on individual columns if you want/need. Here are a few articles to look at:
https://msdn.microsoft.com/en-us/library/hh230914.aspx#TsqlProcedure
https://msdn.microsoft.com/en-us/library/ms144250%28v=sql.105%29.aspx
Here are a few SQL snippets you can run to view your current server collation, as well as the default collations on each database
SELECT CONVERT (varchar, SERVERPROPERTY('collation'));
SELECT name, collation_name FROM sys.databases;

Related

SQL Server 'Invalid column' on a SELECT query to a temp table - CASE SENSITIVITY issue

I have a case where I have NO control whatsoever on the SQL Server configuration.
Here's my configuration:
SQL Server 2008
SQL Server INSTANCE Collation: Latin_General_BIN (Which I know is case-sensitive)
A given database (Which is not case-sensitive... SQL_Latin1_General_CP1_CI_AS)
Here's the scenario I want... if possible:
Given
CREATE DATABASE given_database;
USE given_database;
CREATE TABLE #test (Field1 nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS);
When
SELECT field1 FROM #test; /*Notice the lower case on field1*/
Then
Invalid column name 'field1'
Is there a way to make this work?
I know this is something that no one would want to have but since I am stuck with this configuration on my client side and we have a lot of legacy code that have different casing in the queries... I wanted to know if there's a work around.
Is there a way to make this work?
Not with a temp table, no.
Tempdb inherits the instance default collation. You've defined the column with a case insensitive collation which should let you ask for value comparisons in a case insensitive manner, but the column name itself falls into the database collation so it needs to be referred to as defined.
CREATE TABLE #test (Field1 nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS);
INSERT INTO #test
VALUES ('test'),('TEST'),('Test')
SELECT field1 FROM #test --should fail
SELECT Field1 FROM #test WHERE Field1 = 'tEst' --should work

SQL collating two tables, will it permanently change the collation?

for example, i'm trying to join the product sales table with the customer info table on two different databases of the same server and i end up getting the "Cannot resolve the collation conflict between Latin1_General_CI_AS... " error...
so i've been reading up about how collate DATABASE_DEFAULT will make the uniqueidentifier columns on two tables match and join together...but is the change temporary (during the query only) or will it actually alter the collation on the 2 tables?
thanks
SELECT V.PRODUCT, V.DESCRIPTION, A.NAMECUST, A.NAMECITY
FROM Warehouse.dbo.v AS V
INNER JOIN Maindata.dbo.Customerdata AS A
ON V.CUSTOMER_NUMBER = A.CUSTOMER_NUMBER COLLATE DATABASE_DEFAULT
When COLLATE is used in a query (not a CREATE/ALTER TABLE, CREATE/ALTER INDEX statement) it overrides the table-table (or database-default) collation with one used just for that query, it's saying "use this collation (comparison algorithm) when comparing values for this query only". It does not affect the underlying representation of data on disk or change any definitions (that's what ALTER is for).
Note that using COLLATE in a query is often a bad code-smell: if your database is designed with correct collation in the first place then this won't be necessary.

SQL Server Invalid Column Name Error

I have an invalid Column Name error when inserting a record to my SQL Server table. Here's the definition:
CREATE TABLE [dbo].[myTable]
(
[id] int IDENTITY(1, 1) NOT NULL,
[person_name] varchar(255) NOT NULL,
[modified_By] varchar(255) NOT NULL
)
ON [PRIMARY] WITH (DATA_COMPRESSION = NONE);
GO
And insert
INSERT INTO myDB.dbo.myTable (id, person_name, modified_By)
VALUES (1, 'Aishwarya', 'admin')
But I get the following error upon execution:
Lookup Error - SQL Server Database Error: Invalid column name
'modified_BY'.
I can SELECT from the column fine. The only thing I've noticed in error is that "BY" is capitalized, contrary to the table definition. Any ideas?
UPDATE: Updating all the syntax errors, apologeez
Is your database set to a case sensitive collation? You can check by running this query:
SELECT DATABASEPROPERTYEX('<Insert Database Name>', 'Collation') SQLCollation;
Case insensitive collations usually have CI in the name, such as SQL_Latin1_General_CP1_CI_AS.
Where as case sensitive collation might be something like Latin1_General_BIN.
If the database has a case sensitive collation, then the capitalization in the T-SQL must match the column definition.
Your post here doesn't include the modified_BY capitalization in the insert statement, so double check that. If it's capitalized there properly, then check if there are any triggers on the table that might have the improper spelling.
In your INSERT statement do not supply a value for your IDENTITY column "Id". It should look like:
INSERT INTO myDB.dbo.myTable
(person_name, modified_By)
VALUES ('Aishwarya', 'admin')
Not an answer anyone wants to hear, but our DBA dropped and recreated the table (which had triggers set on it) and this has resolved the issue.

"Cannot resolve collation conflict" even after fixing the collation

The current database I'm using "PrimaryDatabase" has the collation "SQL_Latin1_General_CP1_CI_AS", while the "SecondaryDatabase" I'm trying to access has the collation "Arabic_CI_AS"
I changed the collation for the SecondaryDatabase and set it to " SQL_Latin1_General_CP1_CI_AS" and made sure it has been changed as well as in its tables.
However, when i run the query below I still get collation conflict.
select * from [MYSERVER].[SecondaryDatabase].[dbo].[SecondaryTableName]
where ltrim(rtrim([SecondaryTablename])) not in (select ltrim(rtrim(PrimaryFieldname)) from PrimaryTablename where PrimaryFieldName2=1)
One way to make your query work is to use COLLATE clause in order to apply a collation cast on both fields being involved in the predicate of the WHERE clause:
select *
from [MYSERVER].[SecondaryDatabase].[dbo].[SecondaryTableName]
where ltrim(rtrim([SecondaryFieldname])) COLLATE SQL_Latin1_General_CP1_CI_AS
not in (select ltrim(rtrim(PrimaryFieldname)) COLLATE SQL_Latin1_General_CP1_CI_AS
from PrimaryTablename
where PrimaryFieldName2 = 1)
The COLLATE clause applied to PrimaryFieldname might not be necessary, since this is the default collation of the corresponding database (so probably PrimaryFieldname already has this collation).
Another solution is to change the collation at field level, e.g.:
ALTER TABLE SecondaryDatabase
ALTER COLUMN SecondaryFieldname VARCHAR(50)
COLLATE SQL_Latin1_General_CP1_CS_AS NULL

Creating case sensitive catalog

I'm trying to create multiple rows having the same value but different case to a table with a Primary Key defined on a string column.
By default SQL server wouldn't allow you to do that, is there a way I can tell SQL server this is permitted?
By changing ‘Database Collation’ parameter we can control the database case sensitivity.
The default collation is SQL_Latin1_General_CP1_CI_AS (CI => Case-insensitive)
By changing to SQL_Latin1_General_CP1_CS_AS (CS => Case sensitive) you can enable 2 rows having same primary key with different case.
Specify the COLLATION of the column on your table to be case sensitive.
First figure out what collation your database is using.
SELECT DATABASEPROPERTYEX(DB_NAME(), 'Collation') AS CollationUsedBySQLServerDatabase
-- Mine was Finnish_Swedish_CI_AS
Pick the same one for your table, but choose it to be case sensitive (Finnish_Swedish_CS_AS)
create table Users
(
UserName varchar(5000) COLLATE Finnish_Swedish_CS_AS PRIMARY KEY
)
insert Users(UserName)
Values ('Peter'), ('PETER')
select * from Users

Resources