Cannot resolve the collation conflict
I do a fair bit of work with Linked Servers and cross-database queries and sometimes come across the following error when joining between databases with different collations;
Msg 468, Level 16, State 9, Line 1
Cannot resolve the collation conflict between 'Latin1_General_CI_AS' and 'SQL_Latin1_General_Pref_CP850_CI_AS'; in the equal to operation.
To replicate this error run the below TSQL to create two databases with tables and data.
-- Create first database
CREATE DATABASE database1 COLLATE Latin1_General_CI_AS;
GO
-- Create second database
CREATE DATABASE database2 COLLATE SQL_Latin1_General_Pref_CP850_CI_AS;
GO
USE database1;
GO
-- Create Customer table in database1
CREATE TABLE Customer
(
CustID INTEGER NOT NULL IDENTITY(1, 1) PRIMARY KEY CLUSTERED,
FirstName VARCHAR(30) NOT NULL,
LastName VARCHAR(30) NOT NULL,
DOB DATETIME NOT NULL,
StartDate DATETIME NOT NULL DEFAULT GETDATE()
);
GO
USE database2;
GO
-- Create Customer table in database2
CREATE TABLE Customer
(
CustID INTEGER NOT NULL IDENTITY(1, 1) PRIMARY KEY CLUSTERED,
FirstName VARCHAR(30) NOT NULL,
LastName VARCHAR(30) NOT NULL,
DOB DATETIME NOT NULL,
StartDate DATETIME NOT NULL DEFAULT GETDATE()
);
GO
USE database1;
GO
-- Insert test data
INSERT INTO dbo.Customer
(
FirstName,
LastName,
DOB
)
SELECT 'Joe', 'Bloggs', '1975-01-01 00:00:00'
UNION ALL
SELECT'Dave', 'Smith', '1977-10-11 00:00:00'
UNION ALL
SELECT'Fred', 'Bloggs', '1965-11-28 00:00:00'
UNION ALL
SELECT'Sue', 'Smith', '1974-06-17 00:00:00'
UNION ALL
SELECT 'Steve', 'Smith', '1981-07-07 00:00:00';
GO
USE database2;
GO
-- Insert test data
INSERT INTO dbo.Customer
(
FirstName,
LastName,
DOB
)
SELECT 'Joe', 'Bloggs', '1975-01-01 00:00:00'
UNION ALL
SELECT'Dave', 'Smith', '1977-10-11 00:00:00'
UNION ALL
SELECT'Fred', 'Bloggs', '1965-11-28 00:00:00'
UNION ALL
SELECT'Sue', 'Smith', '1974-06-17 00:00:00'
UNION ALL
SELECT 'Steve', 'Smith', '1981-07-07 00:00:00';
GO
Run the following query to observe the collation conflict.
-- Cross-database query causing the collation conflict
SELECT *
FROM dbo.Customer c1
INNER JOIN database1.dbo.Customer AS c2
ON c1.FirstName = c2.FirstName
AND c1.LastName = c2.LastName;
You could fix this by changing the collation in one of the databases, i.e.
-- Set database2 to the same collation as database1
ALTER DATABASE database2 COLLATE Latin1_General_CI_AS;
-- Change VARCHAR columns on our existing tables
ALTER TABLE Customer ALTER COLUMN FirstName VARCHAR(30) COLLATE Latin1_General_CI_AS;
ALTER TABLE Customer ALTER COLUMN LastName VARCHAR(30) COLLATE Latin1_General_CI_AS;
Sometimes you may not want, or be able, to change a database in this way. In these situations you can add COLLATE DATABASE_DEFAULT to the JOINS or expressions in your query.
-- Using COLLATE DATABASE_DEFAULT
SELECT *
FROM dbo.Customer c1
INNER JOIN database1.dbo.Customer AS c2
ON c1.FirstName = c2.FirstName COLLATE DATABASE_DEFAULT
AND c1.LastName = c2.LastName COLLATE DATABASE_DEFAULT;