问题
I'm an IT consultant that usually manages hardware and networks but our programmers are on leave at the moment. I've made some modifications to a MSSQL query that runs over two databases on each of our 15 site's Practice Management Software servers and I'm getting an error on a few of the servers relating to a collation conflict.
On most of our site's servers it runs fine, but there is 4 out the 15 servers that appear two have the databases using different collation for some reason.
I've looked into trying to change the collation, but it didn't go well, so I was hoping maybe I could tweak the query so the difference in collation didn't matter for these servers. In fact, it'd be better if the query was 'collation agnostic' so that I could use the same query across all servers without a care for the collation... Can this be done?
The exact error is
Msg 446, Level 16, State 11, Line 1 Cannot resolve collation conflict between "Latin1_General_CI_AS" and "SQL_Latin1_General_CP1_CI_AS" in CASE operator for DISTINCT operation.
Msg 446, Level 16, State 11, Line 1 Cannot resolve collation conflict between "Latin1_General_CI_AS" and "SQL_Latin1_General_CP1_CI_AS" in CASE operator for DISTINCT operation.
And the query I'm running is:
SELECT DISTINCT
-- setup columns
[cases].[reference] as MatterNumber,
[dd_entity_d2].[type] as ClientType,
[dd_client].[clientname] as MatterName,
CASE WHEN [dd_entity_d2].[type] ='Individual' THEN etClient.FirstName ELSE [dd_entity_d4].[firstname] END AS FirstName,
CASE WHEN [dd_entity_d2].[type] ='Individual' THEN etClient.LastName ELSE [dd_entity_d4].[lastname] END AS LastName,
CASE WHEN [dd_entity_d2].[type] ='Individual' THEN [dd_entity_d2].[email] ELSE [dd_entity_d4].[email] END AS Email,
etActing.[PreferredName] ActingPerson,
[cases].[category] as MatterType,
mt.CreatedOn as MatterOpened,
case mt.[Status]
when 0 then 'In Progress'
When 1 then 'On Hold'
when 2 then 'Completed'
when 3 then 'Not Proceeding'
else 'Unknown' end as MatterStatus
-- mt.LastUpdatedOn as LastModified,
-- end columns
-- setup data
FROM PracticeEvolve_doc.dbo.[cases]
INNER JOIN PracticeEvolve_c1.dbo.DocumaticsMap dm on dm.DocumaticsID = [cases].ID and dm.Entitytype = 'Matter'
INNER JOIN PracticeEvolve_c1.dbo.[Matter] mt on mt.Matterid = dm.ClickOneID
INNER JOIN PracticeEvolve_c1.dbo.[Client] cl on mt.ClientID = cl.ClientID
INNER JOIN PracticeEvolve_c1.dbo.[Entity] etClient on cl.EntityID = etClient.EntityID
LEFT JOIN PracticeEvolve_c1.dbo.EmployeeMatter emActing on emActing.MatterID = mt.MatterID and emActing.AssociationTypeID = 15
LEFT JOIN PracticeEvolve_c1.dbo.Employee eActing on eActing.EmployeeID = emActing.EmployeeID
LEFT JOIN PracticeEvolve_c1.dbo.Entity etActing on etActing.EntityID = eActing.EntityID
LEFT JOIN PracticeEvolve_doc.dbo.[dd_client] ON [dd_client].[id]=[cases].[clientid]
LEFT JOIN PracticeEvolve_doc.dbo.[dd_manytomany] AS [dd_manytomanydd_entity_d2] ON [dd_manytomanydd_entity_d2].[fkid] = [dd_client].[fk_entities]
LEFT JOIN PracticeEvolve_doc.dbo.[dd_entity] as [dd_entity_d2] ON [dd_entity_d2].[id] = [dd_manytomanydd_entity_d2].[pkid]
LEFT JOIN PracticeEvolve_doc.dbo.[dd_manytomany] AS [dd_manytomanydd_party_d3] ON [dd_manytomanydd_party_d3].[fkid] = [dd_entity_d2].[fk_parties]
LEFT JOIN PracticeEvolve_doc.dbo.[dd_party] as [dd_party_d3] ON [dd_party_d3].[id] = [dd_manytomanydd_party_d3].[pkid]
LEFT JOIN PracticeEvolve_doc.dbo.[dd_manytomany] AS [dd_manytomanydd_entity_d4] ON [dd_manytomanydd_entity_d4].[fkid] = [dd_party_d3].[fk_entity]
LEFT JOIN PracticeEvolve_doc.dbo.[dd_entity] as [dd_entity_d4] ON [dd_entity_d4].[id] = [dd_manytomanydd_entity_d4].[pkid]
-- end data
-- setup filters
WHERE [cases].[deleted]=0
-- AND DATEPART(m, mt.CreatedOn) = DATEPART(m, DATEADD(m, -1, getdate()))
-- AND DATEPART(yyyy, mt.CreatedOn) = DATEPART(yyyy, DATEADD(m, -1, getdate()))
AND mt.CreatedOn >= '2015-07-01'
-- AND [dd_entity_d2].[type] = 'Individual'
-- AND mt.LastUpdatedOn >= '2017-04-02'
-- AND mt.[status] = 0
-- end filters
-- setup sort
ORDER BY Email ASC
-- end sort and query
PracticeEvolve_c1 is SQL_Latin1_General_CP1_CI_AS and PracticeEvolve_doc is Latin1_General_CI_AS.
I'm out of my depth here and would greatly appreciate any help you may be able to offer.
Cheers - Reece
EDIT: FWIW - this is the error I got when I tried to change the database collation:
The object 'MonthToDays365' is dependent on database collation. The database collation cannot be changed if a schema-bound object depends on it. Remove the dependencies on the database collation and then retry the operation
回答1:
Just amend the CASE expression and include the COLLATE
command
CASE WHEN [dd_entity_d2].[type] COLLATE SQL_Latin1_General_CP1_CI_AS
='Individual'
THEN etClient.FirstName COLLATE SQL_Latin1_General_CP1_CI_AS
ELSE [dd_entity_d4].[firstname] COLLATE SQL_Latin1_General_CP1_CI_AS
END AS FirstName,
来源:https://stackoverflow.com/questions/48186025/query-over-two-databases-has-error-due-to-collation-mismatch