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.
Cet article SQL Server: “Cannot resolve the collation conflict” in a Stored Procedure est apparu en premier sur Blog dbi services.