2

我正在尝试UNPIVOT在不同数据库中的表上运行存储过程中的语句。我可以在UNPIVOT本地运行良好,但是当我在不同的数据库/服务器上运行它时,会出现以下错误。

The type of column "XXX" conflicts with the type of other columns specified in the UNPIVOT list.

这是我的精简版UNPIVOT

CREATE TABLE temp (
  id nvarchar(100),
  F1 nvarchar(100),
  F2 nvarchar(100),
  F3 decimal(5,0)
)

INSERT INTO temp VALUES(N'100', N'111', N'AAA', 123)
INSERT INTO temp VALUES(N'100', N'222', N'BBB', 456)
INSERT INTO temp VALUES(N'100', N'333', N'CCC', 789) 
INSERT INTO temp VALUES(N'100', N'444', N'DDD', 012)
INSERT INTO temp VALUES(N'100', N'555', N'EEE', 345)

SELECT * FROM (   SELECT
    ID,
    CAST(F1 AS NVARCHAR(MAX)) AS F1,--used in order to normalize the data
    CAST(F2 AS NVARCHAR(MAX)) AS F2,--used in order to normalize the data
    CAST(F3 AS NVARCHAR(MAX)) AS F3--used in order to normalize the data
FROM
    TEMP   ) AS T UNPIVOT(FieldValue for FieldName in (   F1, F2, F3   )) AS UNPVT

SQL小提琴

我确实注意到当我正在使用的表UNPIVOT具有DECIMAL()字段类型时会发生此错误。

一如既往,任何帮助表示赞赏。


更新:似乎在远程服务器上创建视图将允许CAST正确发生。但为什么?我也尝试过使用cte,但没有奏效。我想避免创建视图。希望这不是唯一的解决方案。

4

1 回答 1

4

错误

“XXX”列的类型与 UNPIVOT 列表中指定的其他列的类型冲突。

非常明显,也是更好的信息之一。它告诉您您的 UNPIVOT 列表包含不同类型的列。这是导致此类错误的示例: SQL Fiddle

SELECT * FROM (
  SELECT
    ID,
    CAST(F1 AS NVARCHAR(MAX)) AS F1,
    CAST(F2 AS NVARCHAR(MAX)) AS F2,
    F3  -- note F3 is a decimal column containing decimal values
  FROM
    TEMP
  ) AS T
UNPIVOT(FieldValue for FieldName in (
  F1, F2, F3  -- F3 type is different from F1/F2
  )) AS UNPVT

在本地查询中,鉴于您在问题 SQL Fiddle中编写的查询,它不可能引发此错误,因为您已经将所有列都转换为 NVARCHAR(MAX)。

但是,在远程查询中,SQL Server 似乎在编译时使查询失败。它似乎在 CAST 之前预先验证了数据透视列 - 似乎是因为可以在本地和执行流程中的不同点执行 CAST。对此的解决方法似乎是创建一个可以解析远程服务器上的 CAST 的视图。

解决方法

您可以使用 FOR XML 强制查询远程解析(在 2005 年测试为最低限度的远程服务器),这样做的好处是nvarchar(max)无论如何都将使用提取回来的值以保持一致性。

SELECT *
FROM (
    SELECT n.value('ID[1]','nvarchar(max)') ID
          ,n.value('F1[1]','nvarchar(max)') F1
          ,n.value('F2[1]','nvarchar(max)') F2
          ,n.value('F3[1]','nvarchar(max)') F3
    FROM (   
        SELECT (
            SELECT
                ID,
                F1,
                F2,
                F3
            FROM
                [akltrsvrdb\sqllatin].test1.dbo.temp
            FOR XML PATH('a'), type
        ) XmlPacket
    ) x
    cross apply XmlPacket.nodes('/a') n(n)
) T UNPIVOT(FieldValue for FieldName in (   F1, F2, F3   )) AS UNPVT

SQLKiwi发现使用sql_variant作为 CAST 目标可以使远程查询工作,如此处的聊天记录所示。

SELECT
    *
FROM
    (
        SELECT
            [id],
            CONVERT(sql_variant, [F1]) as F1,
            CONVERT(sql_variant, [F2]) as F2,
            CONVERT(sql_variant, [F3]) as F3,
            CONVERT(sql_variant, CAST([D20] as nvarchar(4000))) as F20--in case the source field is text (Make sure that 4000 is enough characters!)
        FROM
            [server].[database].[scheme].[table]
    ) as t
UNPIVOT(FieldValue for FieldName in ([F1],[F2],[F3],[D20])) as unpvt
于 2012-12-11T20:34:45.480 回答