首页 > 解决方案 > 从不同数据库上的表更新时 - 无法解决排序规则冲突

问题描述

我正在尝试根据不同数据库上另一个表的条件更新一个表,如下所示:

 update Table1
    set Table1.Name=[release].[People].[Details].Name
    from Table1  inner join [release].[People].[Details]  on Table1.AccountNumber =[release].[People].[Details].AccountNumber 

但它会引发错误:

“无法解决等于操作中“Latin1_General_CI_AS”和“SQL_Latin1_General_CP1_CI_AS”之间的排序规则冲突。”

所以我尝试了以下方法:

update Table1
    set Table1.Name=[release].[People].[Details].Name
    from Table1  inner join [release].[People].[Details]  on Table1.AccountNumber =[release].[People].[Details].AccountNumber 
where   Table1.AccountNumber COLLATE DATABASE_DEFAULT =[release].[People].[Details].AccountNumber  COLLATE DATABASE_DEFAULT

我也试过:

update Table1
    set Table1.Name=[release].[People].[Details].Name
    from Table1  inner join [release].[People].[Details]  on Table1.AccountNumber =[release].[People].[Details].AccountNumber 
and  Table1.AccountNumber COLLATE DATABASE_DEFAULT =[release].[People].[Details].AccountNumber  COLLATE DATABASE_DEFAULT

他们不工作。我无法更改表结构。

标签: sql-server

解决方案


排序规则链接到字符串数据类型,并定义它们如何与其他字符串进行比较。例如Latin1_General_CI_AS,最后 4 个字符表示

  • CI:不区分大小写。可以为敏感的CS。
  • AS:上升敏感。可我为麻木不仁。

检查以下示例:

  • Cafe使用上升不敏感返回结果Café相比:

    DECLARE @Text1 VARCHAR(100) = 'Café' -- has ascent
    DECLARE @Text2 VARCHAR(100) = 'Cafe'
    
    SELECT 
        'match'
    WHERE 
        @Text1 COLLATE Latin1_General_CI_AI = 
        @Text2 COLLATE Latin1_General_CI_AI
    
  • 对上升敏感 做同样的事情不会返回结果

    DECLARE @Text1 VARCHAR(100) = 'Café' -- has ascent
    DECLARE @Text2 VARCHAR(100) = 'Cafe'
    
    SELECT 
        'no match'
    WHERE 
        @Text1 COLLATE Latin1_General_CI_AS = 
        @Text2 COLLATE Latin1_General_CI_AS
    
  • 在比较大小写字符时,使用不区分大小写 将匹配:

    DECLARE @Text1 VARCHAR(100) = 'STRONG weak'
    DECLARE @Text2 VARCHAR(100) = 'strong WEAK'
    
    SELECT 
        'match'
    WHERE 
        @Text1 COLLATE Latin1_General_CI_AI = 
        @Text2 COLLATE Latin1_General_CI_AI
    
  • Collat​​es 还会影响记录的分组方式(因为它们与其他行进行比较):

    DECLARE @Table TABLE (String VARCHAR(100))
    INSERT INTO @Table (String) 
    VALUES ('Café'), ('Cafe') -- One with ascent, another without
    
    SELECT 
        String = T.String COLLATE Latin1_General_CI_AI,
        Rows = COUNT(1)
    FROM
        @Table AS T
    GROUP BY
        T.String COLLATE Latin1_General_CI_AI -- Ascent insensitive!
    
    /*
    Results:
        String  Rows
        Café    2
    */
    
  • 但是,如果比较的每一方之间的排序规则不匹配,引擎将不会冒险假设任何一方,因此会引发错误:

    DECLARE @Text1 VARCHAR(100) = 'STRONG weak'
    DECLARE @Text2 VARCHAR(100) = 'strong WEAK'
    
    SELECT 
        'error!'
    WHERE 
        @Text1 COLLATE Latin1_General_CI_AI = 
        @Text2 COLLATE Latin1_General_CS_AI     -- Different collation
    

消息 468,级别 16,状态 9,第 7 行无法解决等于操作中“Latin1_General_CS_AI”和“Latin1_General_CI_AI”之间的排序规则冲突。

在您的错误中,您比较了不同的字符集(不是大小写或上升,而是可用的语言字符)Latin1_General_CI_ASSQL_Latin1_General_CP1_CI_AS.

您可以通过显式转换其中一个以匹配另一个来解决此问题。我不知道哪个是哪个,因此以下解决方案会将两者都转换为同一个:

update Table1 set 
    Name = [release].[People].[Details].Name
from 
    Table1
    inner join [release].[People].[Details] on 
        Table1.AccountNumber COLLATE Latin1_General_CI_AS = 
        [release].[People].[Details].AccountNumber COLLATE Latin1_General_CI_AS

推荐阅读