Infrastructure at your Service

Stéphane Haby

SQL Server: “Cannot resolve the collation conflict” in a Stored Procedure

This week I have a new little challenge by a customer.
By executing a “standard” stored procedure, I have the error:

Msg 468, Level 16, State 9, Procedure Get_logsessions, Line 56 [Batch Start Line 119] Cannot resolve the collation conflict between “Latin1_General_CI_AS” and “Latin1_General_CI_AS_KS_WS” in the equal to operation.

The Stored Procedure named Get_Logsessions is to log all sessions running on the server in a table.

Looking with the query I develop and present you in a precedent blog here.

I can see that my database collation is not the same as the instance collation

Here the script for the Procedure:

CREATE PROCEDURE [dbo].[Get_logsessions]
AS
SET NOCOUNT ON
IF OBJECT_ID(N'[dbo].[logsessions]') IS NULL
	BEGIN
		CREATE TABLE [dbo].[logsessions]
			(
			[clientip] varchar(48),
			[clientname] nvarchar(128)  ,
			[clientinterface] nvarchar(32) ,
			[app] nvarchar(128)  ,
			[auth] nvarchar(40) ,
			[login] nvarchar(128) ,
			[db] nvarchar(128),
			[firstaccess] [datetime] NULL,
			[lastaccess] [datetime] NULL,
			[count] bigint NULL
			)
	END

IF OBJECT_ID(N'tempdb..#sp_who2')  IS NOT NULL
	DROP TABLE #sp_who2
IF OBJECT_ID(N'tempdb..#logsessions')  IS NOT NULL
	DROP TABLE #logsessions

-- Use sp_who2 to be compatible with 2005 to replace [db] = db_name(b.database_id)
CREATE TABLE #sp_who2 (SPID INT,Status VARCHAR(255) ,
      Login  VARCHAR(255)  ,HostName  VARCHAR(255)  ,
      BlkBy  VARCHAR(255) ,DBName  VARCHAR(255)  ,
      Command VARCHAR(255)  ,CPUTime INT,
      DiskIO INT,LastBatch VARCHAR(255)  ,
      ProgramName VARCHAR(255) ,SPID2 INT,
      REQUESTID INT)

INSERT INTO #sp_who2 EXEC sp_who2

SELECT DISTINCT
	[clientip] = a.client_net_address,
	[clientname] = b.host_name ,
	[clientinterface] = b.client_interface_name  ,
	[app] = b.program_name  ,
	[auth] = a.auth_scheme  ,
	[login] = b.login_name ,
	[db] = w.DBName  ,
	[firstaccess] = MIN(b.[login_time]),
	[lastaccess] = MAX(b.[login_time]),
	[count] = Count(*) 
INTO
	#logsessions
FROM 
	sys.dm_exec_connections a
	INNER JOIN sys.dm_exec_sessions b on a.session_id = b.session_id
	INNER JOIN  #sp_who2 w on w.SPID = b.session_id
GROUP BY a.[client_net_address],b.[host_name] ,b.[client_interface_name],b.[program_name] ,a.[auth_scheme],b.[login_name],w.[DBName]

UPDATE
    b
SET
    b.[lastaccess] =  a.[lastaccess],
	b.[count] = b.[count] + 1
FROM 
		#logsessions a
		INNER JOIN [dbo].[logsessions] b
			ON 	a.[clientip] = b.[clientip]  
			AND a.[clientname] = b.[clientname]  
			AND a.[clientinterface] = b.[clientinterface]  
			AND	a.[app] = b.[app]  
			AND a.[auth] = b.[auth] 
			AND a.[login] = b.[login]  
			AND a.[db] = b.[db] 
	WHERE
		DATEDIFF(s,b.[lastaccess] ,a.[lastaccess]) <> 0
		AND
		DATEDIFF(s,b.[firstaccess] ,a.[firstaccess]) <> 0
		AND
		DATEDIFF(s,b.[firstaccess] ,a.[lastaccess]) > 0

INSERT INTO [dbo].[logsessions]
        (
		 [clientip]
        ,[clientname]
        ,[clientinterface]
        ,[app]
        ,[auth]
        ,[login]
        ,[db]
		,[firstaccess],
		[lastaccess],
		[count]
		)
	(
	SELECT
		a.[clientip],a.[clientname] ,a.[clientinterface],a.[app] ,a.[auth], a.[login],a.[db], a.[firstaccess],a.[lastaccess],a.count 
	FROM #logsessions a
	LEFT JOIN [dbo].[logsessions] b
			ON 	a.[clientip] = b.[clientip] 
			AND a.[clientname] = b.[clientname]
			AND a.[clientinterface] = b.[clientinterface]  
			AND	a.[app] = b.[app] 
			AND a.[auth] = b.[auth]
			AND a.[login] = b.[login] 
			AND a.[db] = b.[db]
	WHERE
		b.[clientip] IS NULL
		)

DROP TABLE #logsessions
DROP TABLE #sp_who2

SET NOCOUNT OFF
GO

If I comment the creation of the Stored Procedure and I execute the query , I see my collation conflict:

If I go to the line 67, I’m on the update command:

UPDATE
    b
SET
    b.[lastaccess] =  a.[lastaccess],
	b.[count] = b.[count] + 1
FROM 
		#logsessions a
		INNER JOIN [dbo].[logsessions] b
			ON 	a.[clientip] = b.[clientip]  
			AND a.[clientname] = b.[clientname]  
			AND a.[clientinterface] = b.[clientinterface]  
			AND	a.[app] = b.[app]  
			AND a.[auth] = b.[auth] 
			AND a.[login] = b.[login]  
			AND a.[db] = b.[db] 
	WHERE
		DATEDIFF(s,b.[lastaccess] ,a.[lastaccess])  0
		AND
		DATEDIFF(s,b.[firstaccess] ,a.[firstaccess])  0
		AND
		DATEDIFF(s,b.[firstaccess] ,a.[lastaccess]) > 0

The conflict comes from the update from the table #logsessions to logsessions and the collation from the comparison between the varchar columns from each table in the join.
What can I do?

I will simply aligned the collation for each column with

COLLATE DATABASE_DEFAULT

My new update will be like this:

UPDATE
    b
SET
    b.[lastaccess] =  a.[lastaccess],
	b.[count] = b.[count] + 1
FROM 
		#logsessions a
		INNER JOIN [dbo].[logsessions] b 
			ON 	a.[clientip] = b.[clientip]					COLLATE DATABASE_DEFAULT
			AND a.[clientname] = b.[clientname]				COLLATE DATABASE_DEFAULT
			AND a.[clientinterface] = b.[clientinterface]	COLLATE DATABASE_DEFAULT
			AND	a.[app] = b.[app]							COLLATE DATABASE_DEFAULT
			AND a.[auth] = b.[auth]							COLLATE DATABASE_DEFAULT
			AND a.[login] = b.[login]						COLLATE DATABASE_DEFAULT
			AND a.[db] = b.[db]								COLLATE DATABASE_DEFAULT
	WHERE
		DATEDIFF(s,b.[lastaccess] ,a.[lastaccess])  0
		AND
		DATEDIFF(s,b.[firstaccess] ,a.[firstaccess])  0
		AND
		DATEDIFF(s,b.[firstaccess] ,a.[lastaccess]) > 0


And when I execute the script, no more conflict

I do an alter Store Procedure and execute this new one:

Perfect no more collation conflict!
I think that is important to share with you this issue and hope you will win time if you need to resolve a similar case.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Stéphane Haby
Stéphane Haby

Delivery Manager and Senior Consultant