What
is collation?
Collation
refers to a set of rules that determine how data is sorted and
compared. Character data is sorted using rules that define the
correct character sequence, with options for specifying
- case-sensitivity,
- accent marks,
- kana character types and
- character width.
If A and a, B and b, etc. are treated in the same way then it is case-insensitive. A computer treats A and a differently because it uses ASCII code to differentiate the input. The ASCII value of A is 65, while a is 97. The ASCII value of B is 66 and b is 98.
Accent sensitivity
If a and á, o and ó are treated in the same way, then it is accent-insensitive. A computer treats a and á differently because it uses ASCII code for differentiating the input. The ASCII value of a is 97 and áis 225. The ASCII value of o is 111 and ó is 243.
Kana Sensitivity
When Japanese kana characters Hiragana and Katakana are treated differently, it is called Kana sensitive.
Width sensitivity
When a single-byte character (half-width) and the same character when represented as a double-byte character (full-width) are treated differently then it is width sensitive.
Production server collation error(Log):
Msg
468, Level 16, State 9, Line 1
Cannot resolve the collation
conflict between "SQL_Latin1_General_CP1_CI_AS" and
"Latin1_General_CI_AS" in the equal to operation.
Reproduce this error
in local QA environment:
How
to exploring collation?
Step 1 : What
Collation is SQL installed local server identify below query
SELECT
SERVERPROPERTY('COLLATION')
Step 2 : Identify
databases level Collation
SELECT
NAME,COLLATION_NAME
FROM
SYS.DATABASES
Step 4 : Show the
collation for each column in selected database level
SELECT
C.TABLE_CATALOG
AS DATABASE_NAME
,C.TABLE_SCHEMA
,C.TABLE_NAME
,C.COLUMN_NAME
,DATA_TYPE
,SERVERPROPERTY('COLLATION')
AS SERVER_COLLATION
,CONVERT(SYSNAME,DATABASEPROPERTYEX(D.NAME,'COLLATION'))
AS DATABASE_COLLATION
,C.COLLATION_NAME
AS COLUMN_COLLATION
FROM
INFORMATION_SCHEMA.COLUMNS C
INNER
JOIN SYS.DATABASES D
ON
DB_ID(C.TABLE_CATALOG) = DB_ID(D.NAME)
WHERE
DATA_TYPE IN ('VARCHAR' ,'CHAR','NVARCHAR','NCHAR','TEXT','NTEXT')
In local server level
collation ,database level collation and column level collation are
same collation (“SQL_Latin1_General_CP1_CI_AS”)How to Reproduce local environment?
Step 1:Change the database level collation using the below query
ALTER
DATABASE
FP_Yeti_QA2 SET
SINGLE_USER
WITH
ROLLBACK
IMMEDIATE
GO
ALTER
DATABASE
FP_Yeti_QA2 COLLATE
Latin1_General_CI_AI
GO
ALTER
DATABASE
FP_Yeti_QA2 SET
MULTI_USER
Latin1_General_CI_AI
This is not sql server collation ,This is Windows level collation
existing in production server, That why I changed in local server
also same collation.
Step
2 :Change table level collation means all column collation using the
below script. ( The script will generate all table column
collation querys )
DECLARE
@Table_Name NVARCHAR(100)
SET
@Table_Name =
NULL---
THIS IS THE TableName that you want to change its collation columns
---
if null will set to all tables
DECLARE
@TempTable AS
TABLE
(
ID
INT
IDENTITY
,TableName
NVARCHAR(100)
,ColumnName
NVARCHAR(100)
,TypeName
NVARCHAR(100)
,Max_length
INT
,Collation_Name
NVARCHAR(100)
,EnterDtm
DATETIME
DEFAULT
GETDATE()
)
DECLARE
@NewCollation NVARCHAR(100)
SET
@NewCollation =
'database_default'
---
THIS IS THE COLLATION NAME THAT YOU WANT TO CHANGE
INSERT
INTO
@TempTable(TableName,ColumnName,TypeName,Max_length,Collation_Name)
SELECT
QUOTENAME(SCHEMA_NAME(tables.schema_id))
+
'.'
+
QUOTENAME(tables.name)
AS
TableName
,all_columns.name
AS
ColumnName
,type_name(all_columns.user_type_id)
,all_columns.max_length
,all_columns.collation_name
from
sys.all_columns
INNER
JOIN
sys.tables
ON
tables.object_id
=
all_columns.object_id
AND
collation_name IS
NOT
NULL
AND
all_columns.collation_name
!=
@NewCollation
WHERE
tables.object_id
=
ISNULL(object_id(@Table_Name),all_columns.object_id)
DECLARE
@TableID SMALLINT
SET
@TableID =
(SELECT
MIN(ID)
FROM
@TempTable)
DECLARE
@Query NVARCHAR(1000),@TableName
NVARCHAR(100),@ColumnName
NVARCHAR(100),@TypeName
NVARCHAR(100)
,@Size
INT
WHILE
@TableID IS
NOT
NULL
BEGIN
SET
@TableName =
(SELECT
TableName FROM
@TempTable WHERE
ID =
@TableID)
SET
@ColumnName =
(SELECT
QUOTENAME(ColumnName)
FROM
@TempTable WHERE
ID =
@TableID)
SET
@TypeName =
(SELECT
TypeName FROM
@TempTable WHERE
ID =
@TableID)
SET
@Size =
(SELECT
Max_length FROM
@TempTable WHERE
ID =
@TableID)
SET
@Query='ALTER
TABLE '
+
@TableName +
'
ALTER COLUMN '
+
@ColumnName +
'
'
+
@TypeName+
ISNULL
('('
+CAST(@Size
AS
VARCHAR(200))+')',
'')
+'
COLLATE '+
@NewCollation
PRINT
(@Query)
--execute
sp_executesql @Query
SET
@TableID =
(SELECT
MIN(ID)
FROM
@TempTable WHERE
ID >
@TableID)
END
This
is the way to generate script all table in select database level and
execute single usermode
Ex:-
ALTER
DATABASE
FP_Yeti_QA2 SET
SINGLE_USER
WITH
ROLLBACK
IMMEDIATE
GO
Here
column level generating scripts
GO
ALTER
DATABASE
FP_Yeti_QA2 SET
MULTI_USER
How to Error Fix:
Step 1:Change the database level collation using the below query
ALTER
DATABASE
FP_Yeti_QA2 SET
SINGLE_USER
WITH
ROLLBACK
IMMEDIATE
GO
ALTER
DATABASE
FP_Yeti_QA2 COLLATE
SQL_Latin1_General_CP1_CI_AS
GO
ALTER
DATABASE
FP_Yeti_QA2 SET
MULTI_USER
SQL_Latin1_General_CP1_CI_AS
this is sql server default collation all system databases follow the
same collation better we should follow user databases also.
Step
2 :Change table level collation means all column collation inherit
the database level collation (database_default) using the below
script. ( The script will generate all table column collation querys
)
DECLARE
@Table_Name NVARCHAR(100)
SET
@Table_Name =
NULL---
THIS IS THE TableName that you want to change its collation columns
---
if null will set to all tables
DECLARE
@TempTable AS
TABLE
(
ID
INT
IDENTITY
,TableName
NVARCHAR(100)
,ColumnName
NVARCHAR(100)
,TypeName
NVARCHAR(100)
,Max_length
INT
,Collation_Name
NVARCHAR(100)
,EnterDtm
DATETIME
DEFAULT
GETDATE()
)
DECLARE
@NewCollation NVARCHAR(100)
SET
@NewCollation =
'database_default'
---
THIS IS THE COLLATION NAME THAT YOU WANT TO CHANGE
INSERT
INTO
@TempTable(TableName,ColumnName,TypeName,Max_length,Collation_Name)
SELECT
QUOTENAME(SCHEMA_NAME(tables.schema_id))
+
'.'
+
QUOTENAME(tables.name)
AS
TableName
,all_columns.name
AS
ColumnName
,type_name(all_columns.user_type_id)
,all_columns.max_length
,all_columns.collation_name
from
sys.all_columns
INNER
JOIN
sys.tables
ON
tables.object_id
=
all_columns.object_id
AND
collation_name IS
NOT
NULL
AND
all_columns.collation_name
!=
@NewCollation
WHERE
tables.object_id
=
ISNULL(object_id(@Table_Name),all_columns.object_id)
DECLARE
@TableID SMALLINT
SET
@TableID =
(SELECT
MIN(ID)
FROM
@TempTable)
DECLARE
@Query NVARCHAR(1000),@TableName
NVARCHAR(100),@ColumnName
NVARCHAR(100),@TypeName
NVARCHAR(100)
,@Size
INT
WHILE
@TableID IS
NOT
NULL
BEGIN
SET
@TableName =
(SELECT
TableName FROM
@TempTable WHERE
ID =
@TableID)
SET
@ColumnName =
(SELECT
QUOTENAME(ColumnName)
FROM
@TempTable WHERE
ID =
@TableID)
SET
@TypeName =
(SELECT
TypeName FROM
@TempTable WHERE
ID =
@TableID)
SET
@Size =
(SELECT
Max_length FROM
@TempTable WHERE
ID =
@TableID)
SET
@Query='ALTER
TABLE '
+
@TableName +
'
ALTER COLUMN '
+
@ColumnName +
'
'
+
@TypeName+
ISNULL
('('
+CAST(@Size
AS
VARCHAR(200))+')',
'')
+'
COLLATE '+
@NewCollation
PRINT
(@Query)
--execute
sp_executesql @Query
SET
@TableID =
(SELECT
MIN(ID)
FROM
@TempTable WHERE
ID >
@TableID)
END
Ex:-
ALTER
DATABASE
FP_Yeti_QA2 SET
SINGLE_USER
WITH
ROLLBACK
IMMEDIATE
GO
Here
column level generating scripts
GO
ALTER
DATABASE
FP_Yeti_QA2 SET
MULTI_USER
Restart
the database server.