【问题标题】:The type of column conflicts with the type of other columns specified in the UNPIVOT list列的类型与 UNPIVOT 列表中指定的其他列的类型冲突
【发布时间】:2016-06-14 13:40:03
【问题描述】:

我在不同的数据库中有两个表,我试图将它们合并在一起以创建资产列表及其读数。我想出了以下查询:

use [db1]
DECLARE @colsUnpivot AS NVARCHAR(MAX),
   @query  AS NVARCHAR(MAX)
select @colsUnpivot 
  = stuff((select ','+quotename(C.name)
           FROM sys.columns c
           where c.object_id = OBJECT_ID('db1.dbo.RUNTIME') and c.name != 'timestamp'
           for xml path('')), 1, 1, '')


use [db2]
set @query = '
SELECT
  a.[ID],
  a.[ASSETCLASS],
  a.[ASSETID],
  a.[READINGNAME],
  CONVERT(nvarchar(max), a.[SCADA_TAG]) as [SCADA_TAG],
  b.timestamp AS [READINGDATE],
  b.scada_value AS [READING]
/*,[PROCESSED]*/ FROM [scada].[PREPROCESSING] a
LEFT JOIN (SELECT
  [timestamp],
  CONVERT(nvarchar(max), [SCADA_TAG]) as [SCADA_TAG],
  [SCADA_VALUE]
FROM [db1].[dbo].[RUNTIME] UNPIVOT (SCADA_VALUE FOR SCADA_TAG IN ('+ @colsUnpivot +')) u) b
  ON a.scada_tag = b.scada_tag'

  exec sp_executesql @query;

但是,我在运行查询时收到以下错误消息:

当我查看所提到的列的数据类型时,db1 数据库对于我要选择的列有两种不同的数据类型——浮点数和整数。我试图将这些列名称从 db1 放入 db2 的列是数据类型 nvarchar(100)。我试过铸造并将 SCADA_TAG 转换为没有成功。我刚刚从另一个开发人员那里继承了这个 SQL 集成,我对枢轴和非枢轴功能感到生疏。任何帮助或建议将不胜感激。

【问题讨论】:

  • 如果您对列中的所有行进行反透视 - 必须是相同的数据类型。

标签: sql sql-server dynamic-sql unpivot


【解决方案1】:

我知道这可能会迟到。但是您可以首先尝试的几乎是在两个表上进行模式比较。检查哪些列或数据类型是否不同。请参阅下面的脚本。

SELECT c.name AS ColumnName,
    t.name AS DataType,
    c.max_length
FROM [DB1].sys.columns  c
INNER JOIN [DB1].sys.types  t 
    ON c.user_type_id=t.user_type_id
WHERE OBJECT_NAME(object_id ) = 'TableName'


 EXCEPT

SELECT c.name AS ColumnName,
    t.name AS DataType,
    c.max_length
FROM [DB2].sys.columns  c
INNER JOIN [DB2].sys.types t 
    ON c.user_type_id=t.user_type_id
WHERE OBJECT_NAME(OBJECT_ID) = 'TableName'

【讨论】:

    【解决方案2】:

    我最终做的(这可能不是最有效的处理方式)是从源数据库中获取列并将它们转换并选择为 NVARCHAR(100) 列。

    USE [db1]
    DECLARE @tagNames AS nvarchar(max),
            @query AS nvarchar(max)
    SELECT
      @tagNames
      = STUFF((SELECT
        ', CAST(' + QUOTENAME(C.name) + ' as nvarchar(100)) as ' + QUOTENAME(c.name)
      FROM sys.columns c
      WHERE c.object_id = OBJECT_ID('db1.dbo.RUNTIME')
      AND c.name != 'timestamp'
      FOR xml PATH (''))
      , 1, 1, '')
    
    USE [db2]
    SET @query = 'select [timestamp], ' + @tagNames + ' into test_runtime from
      [db1].dbo.RUNTIME'
    EXEC sp_executesql @query
    

    这为我提供了一个与原始表具有相同结构和值的表,但所有列都已转换为 NVARCHAR,但 [timestamp] 列除外。然后,我可以运行以下 SQL 来返回资产和读数的未透视和合并结果集:

    DECLARE @colsUnpivot AS nvarchar(max),
            @query AS nvarchar(max)
    SELECT
      @colsUnpivot
      = STUFF((SELECT
        ',' + QUOTENAME(C.name)
      FROM sys.columns c
      WHERE c.object_id = OBJECT_ID('dbo.test_RUNTIME')
      AND c.name != 'timestamp'
      FOR xml PATH (''))
      , 1, 1, '')
    
    SET @query = '
    SELECT
      a.[ID],
      a.[ASSETCLASS],
      a.[ASSETID],
      a.[READINGNAME],
      a.[SCADA_TAG],
      b.timestamp AS [READINGDATE],
      b.scada_value AS [READING]
    FROM [scada].[PREPROCESSING] a
    LEFT JOIN (SELECT
      [timestamp],
      [scada_tag],
      [SCADA_VALUE]
    FROM [dbo].[test_RUNTIME] UNPIVOT (SCADA_VALUE FOR SCADA_TAG IN (' + @colsUnpivot + ')) u) b
      ON a.scada_tag = b.scada_tag'
    
    EXEC sp_executesql @query;
    GO
    

    如果有更有效的方法,我会全力以赴。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-21
      • 2021-09-29
      • 1970-01-01
      相关资源
      最近更新 更多