【问题标题】:Temp Table collation conflict - Error : Cannot resolve the collation conflict between Latin1* and SQL_Latin1*临时表排序规则冲突 - 错误:无法解决 Latin1* 和 SQL_Latin1* 之间的排序规则冲突
【发布时间】:2014-02-15 09:55:43
【问题描述】:

我无法更新临时表。这是我的查询

CREATE TABLE #temp_po(IndentID INT, OIndentDetailID INT, OD1 VARCHAR(50), OD2 VARCHAR(50), 
        OD3 VARCHAR(50), ORD VARCHAR(50), NIndentDetailID INT, ND1 VARCHAR(50), ND2 VARCHAR(50), 
        ND3 VARCHAR(50), NRD VARCHAR(50), Quantity DECIMAL(15,3))

        INSERT INTO #temp_po(IndentID, OIndentDetailID, OD1, OD2, OD3, ORD)
        SELECT ID.IndentID, ID.IndentDetailID, ID.D1, ID.D2, ID.D3, ID.RandomDimension 
        FROM STR_IndentDetail ID WHERE ID.IndentID = @IndentID

        UPDATE 
            t 
        SET
            t.ND1 = CASE WHEN D.D1 = '' THEN NULL ELSE D.D1 END,
            t.ND2 = CASE WHEN D.D2 = '' THEN NULL ELSE D.D2 END,
            t.ND3 = CASE WHEN D.D3 = '' THEN NULL ELSE D.D3 END,
            t.NRD = CASE WHEN D.RandomDim = '' THEN NULL ELSE D.RandomDim END,
            t.Quantity = D.PurchaseQty
        FROM
            #temp_po t INNER JOIN @detail D ON D.IndentDetailID = t.OIndentDetailID
        WHERE
            t.IndentID = @IndentID

但它给出了错误

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

如何解决这个问题?

我的tempdb 排序规则是Latin1_General_CI_AI,而我的实际数据库排序规则是SQL_Latin1_General_CP1_CI_AS

【问题讨论】:

  • 正如@StuartLC 下面所说,这是您的列排序规则(可能是从数据库继承的)和 master 之间的冲突,因为 tempdb 默认为 master db 的排序规则。最简单的解决方案是将 COLLATE DATABASE_DEFAULT 附加到每个 (n)char/(n)varchar 数据类型,以便始终创建临时表以匹配您正在使用的数据库。

标签: sql sql-server collation tempdb


【解决方案1】:

发生这种情况是因为 #tempdb.temp_po.OD1STR_IndentDetail.D1 上的排序规则不同(具体来说,请注意 #tempdb 是一个不同的系统数据库,这通常是为什么它会有一个默认的排序规则意见,不像你自己的您可能提供了更具体意见的数据库和表格)。

由于您可以控制临时表的创建,因此解决此问题的最简单方法似乎是在临时表中使用与 STR_IndentDetail 表相同的排序规则创建 *char 列:

CREATE TABLE #temp_po(
    IndentID INT, 
    OIndentDetailID INT, 
    OD1 VARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS, 
    .. Same for the other *char columns   

在您无法控制表创建的情况下,当您连接列时,另一种方法是在发生错误的 DML 中添加显式 COLLATE 语句,通过 COLLATE SQL_Latin1_General_CP1_CI_AS 或更简单,使用COLLATE DATABASE_DEFAULT

SELECT * FROM #temp_po t INNER JOIN STR_IndentDetail s 
   ON t.OD1 = s.D1 COLLATE SQL_Latin1_General_CP1_CI_AS;

或者,更简单

SELECT * FROM #temp_po t INNER JOIN STR_IndentDetail s 
   ON t.OD1 = s.D1 COLLATE DATABASE_DEFAULT;

SqlFiddle here

【讨论】:

【解决方案2】:

默认情况下,临时表采用服务器的排序规则。因此,使用临时表更新所有存储过程只更改服务器排序规则。

查看此链接以获取Set or Change the Server Collation

这对我有用。

【讨论】:

    【解决方案3】:

    我们现在遇到了同样的问题。我们没有将排序规则添加到临时表创建(或每个临时表连接),而是将临时表创建更改为表变量声明。

    【讨论】:

      【解决方案4】:

      更改服务器排序规则不是一个直接的决定,服务器上的其他数据库可能会受到影响。对于现有的填充数据库,即使更改数据库排序规则也不总是可取的。我认为在创建临时表时使用COLLATE DATABASE_DEFAULT 是最安全和最简单的选择,因为它不会在你的 sql 中硬编码任何排序规则。例如:

      CREATE TABLE #temp_table1
      (
          column_1    VARCHAR(2)  COLLATE database_default
      )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-06
        • 2011-04-17
        • 1970-01-01
        相关资源
        最近更新 更多