解决 "Latin1_General_CI_AS" 和 "SQL_Latin1_General_CP1_CI_AS" 之间的排序规则冲突
Resolve collation conflict between "Latin1_General_CI_AS" and "SQL_Latin1_General_CP1_CI_AS"
我该如何解决这个问题?
如果我删除第 2 行,查询将正常工作。
SELECT case when ID_DonVi_Di > 0 then 'dv'+cast(ID_DonVi_Di as nvarchar) else MaChiNhanh_Di end as ID_NoiDi
, case when ID_DonVi_Di > 0 then dvdi.Ten_DonViNgoai else cndi.TenChiNhanh end as NoiDi
, case when ID_DonVi_Den > 0 then 'dv'+cast(ID_DonVi_Den as nvarchar) else MaChiNhanh_Den end as ID_NoiDen
--, case when ID_DonVi_Den > 0 then dvden.Ten_DonViNgoai else cnden.TenChiNhanh end as NoiDen
FROM
[dbo].[ToTrinh] a
left join
dbo.DM_CHINHANH cndi on a.MaChiNhanh_Di = cndi.MaChiNhanh COLLATE Latin1_General_CI_AS
left join
dbo.DM_CHINHANH cnden on a.MaChiNhanh_Den = cnden.MaChiNhanh COLLATE Latin1_General_CI_AS
left join
[dbo].DM_DonViNgoai dvdi on a.ID_DonVi_Di = dvdi.ID_DonViNgoai
left join
[dbo].DM_DonViNgoai dvden on a.ID_DonVi_Den = dvden.ID_DonViNgoai
where a.TonTai = 1
enter image description here
您需要更改一个字段的排序规则以匹配另一字段的排序规则。
例如,如果 A 列具有排序规则 Latin1_General_CI_AS...
并且 B 列具有排序规则 SQL_Latin1_General_CP1_CI_AS...
你可以这样做:
CASE WHEN X > 0 THEN A ELSE B COLLATE Latin1_General_CI_AS END
或者像这样的东西:
CASE WHEN X > 0 THEN A COLLATE SQL_Latin1_General_CP1_CI_AS ELSE B END
@Jortx 的回答 100% 正确,解决了这个特定查询的问题。但是,如果您发现需要一遍又一遍地执行此操作,则可能值得更改其中一列的排序规则以匹配模式中的另一列。一般语法是:
alter table dbo.foo
alter column bar nvarchar(400) collate SQL_Latin1_General_CP1_CI_AS;
也就是说,您将按照您希望的方式指定列的所有属性。请注意,这是一个 size-of-data 操作,因此根据 table 中的行数,它可能需要一段时间。此外,还需要删除列上的任何 non-clustered 索引。
那么这样的事情是怎么发生的呢?据推测,您的一位开发人员在某个时候在数据库具有不同默认排序规则的另一个环境中创建了 table。然后,在准备好将 table 部署到生产环境的过程中,编写了 table 脚本。该脚本明确说明了这些列的排序规则,因此无论开发人员在编写脚本时的排序规则是什么,都会在环境中传递。我建议追下去。不是为了严词相向,而是为了防止这种事情发生。
在同一个数据库中使用不同的排序规则是否有正当理由?当然!但是在这种情况下,所涉及的两个归类非常相似,以至于感觉其中一个是疏忽。
我该如何解决这个问题?
如果我删除第 2 行,查询将正常工作。
SELECT case when ID_DonVi_Di > 0 then 'dv'+cast(ID_DonVi_Di as nvarchar) else MaChiNhanh_Di end as ID_NoiDi
, case when ID_DonVi_Di > 0 then dvdi.Ten_DonViNgoai else cndi.TenChiNhanh end as NoiDi
, case when ID_DonVi_Den > 0 then 'dv'+cast(ID_DonVi_Den as nvarchar) else MaChiNhanh_Den end as ID_NoiDen
--, case when ID_DonVi_Den > 0 then dvden.Ten_DonViNgoai else cnden.TenChiNhanh end as NoiDen
FROM
[dbo].[ToTrinh] a
left join
dbo.DM_CHINHANH cndi on a.MaChiNhanh_Di = cndi.MaChiNhanh COLLATE Latin1_General_CI_AS
left join
dbo.DM_CHINHANH cnden on a.MaChiNhanh_Den = cnden.MaChiNhanh COLLATE Latin1_General_CI_AS
left join
[dbo].DM_DonViNgoai dvdi on a.ID_DonVi_Di = dvdi.ID_DonViNgoai
left join
[dbo].DM_DonViNgoai dvden on a.ID_DonVi_Den = dvden.ID_DonViNgoai
where a.TonTai = 1
enter image description here
您需要更改一个字段的排序规则以匹配另一字段的排序规则。
例如,如果 A 列具有排序规则 Latin1_General_CI_AS...
并且 B 列具有排序规则 SQL_Latin1_General_CP1_CI_AS...
你可以这样做:
CASE WHEN X > 0 THEN A ELSE B COLLATE Latin1_General_CI_AS END
或者像这样的东西:
CASE WHEN X > 0 THEN A COLLATE SQL_Latin1_General_CP1_CI_AS ELSE B END
@Jortx 的回答 100% 正确,解决了这个特定查询的问题。但是,如果您发现需要一遍又一遍地执行此操作,则可能值得更改其中一列的排序规则以匹配模式中的另一列。一般语法是:
alter table dbo.foo
alter column bar nvarchar(400) collate SQL_Latin1_General_CP1_CI_AS;
也就是说,您将按照您希望的方式指定列的所有属性。请注意,这是一个 size-of-data 操作,因此根据 table 中的行数,它可能需要一段时间。此外,还需要删除列上的任何 non-clustered 索引。
那么这样的事情是怎么发生的呢?据推测,您的一位开发人员在某个时候在数据库具有不同默认排序规则的另一个环境中创建了 table。然后,在准备好将 table 部署到生产环境的过程中,编写了 table 脚本。该脚本明确说明了这些列的排序规则,因此无论开发人员在编写脚本时的排序规则是什么,都会在环境中传递。我建议追下去。不是为了严词相向,而是为了防止这种事情发生。
在同一个数据库中使用不同的排序规则是否有正当理由?当然!但是在这种情况下,所涉及的两个归类非常相似,以至于感觉其中一个是疏忽。