【问题标题】:CTE error: "Types don't match between the anchor and the recursive part"CTE 错误:“锚点和递归部分之间的类型不匹配”
【发布时间】:2010-12-22 17:40:15
【问题描述】:

我正在执行以下语句:

;WITH cte AS (
  SELECT 
    1 as rn, 
    'name1' as nm
  UNION ALL
  SELECT 
    rn + 1,
    nm = 'name' + CAST((rn + 1) as varchar(255))
  FROM cte a WHERE rn < 10)
SELECT * 
FROM cte

...以错误结束...

Msg 240, Level 16, State 1, Line 2
Types don't match between the anchor and the recursive part in column "nm" of recursive query "cte".

我在哪里犯错了?

【问题讨论】:

    标签: sql sql-server tsql common-table-expression


    【解决方案1】:

    正是它所说的:

    'name1' 的数据类型与'name' + CAST((rn+1) as varchar(255)) 不同

    试试这个(未经测试)

    ;with cte as
    (
    select 1 as rn, CAST('name1' as varchar(259)) as nm
    union all
    select rn+1,nm = 'name' + CAST((rn+1) as varchar(255))
    from cte a where rn<10)
    select * from cte
    

    基本上,您也必须确保长度匹配。对于递归位,如果再次失败,您可能必须使用CAST('name' AS varchar(4))

    【讨论】:

    • 先生,这正是我所做的。 CAST(1 as varchar(255))
    • Stackoverflow 在我问之前再次回答了我的问题。谢谢@priyanka 和@gbn
    • 以防万一,如果您仍然收到该错误,您还应该确保数据库的排序规则和表的排序规则相同。换句话说,排序规则在 CTE 递归查询中应该是相同的。
    【解决方案2】:

    你需要同时转换两个 nm 字段

    ;with cte as
    (
    select  1 as rn, 
            CAST('name1' AS VARCHAR(255)) as nm
    union all
    select  rn+1,
            nm = CAST('name' + CAST((rn+1) as varchar(255)) AS VARCHAR(255))
    from cte a where rn<10)
    select * from cte
    

    【讨论】:

    • 这就是我所做的。 CAST(1 作为 varchar(255)) 。一个愚蠢的错误忘了施法。(:
    • 在与 sql 战斗后,我最终将两者都转换为十进制并解决了我的问题。谢谢!
    【解决方案3】:

    对我来说,问题在于不同的排序规则。

    只有这对我有帮助:

    ;WITH cte AS (
      SELECT 
        1 AS rn, 
        CAST('name1' AS NVARCHAR(4000)) COLLATE DATABASE_DEFAULT AS nm
      UNION ALL
      SELECT 
        rn + 1,
        nm = CAST('name' + CAST((rn + 1) AS NVARCHAR(255)) AS NVARCHAR(4000)) COLLATE DATABASE_DEFAULT
      FROM cte a WHERE rn < 10)
    SELECT * 
    FROM cte;
    

    希望它可以帮助别人。

    【讨论】:

      【解决方案4】:
      ;with cte as
      (
      select 1 as rn, 'name' + CAST(1 as varchar(255)) as nm
      union all
      select rn+1,nm = 'name' + CAST((rn+1) as varchar(255))
      from cte a where rn<10)
      select * from cte
      

      【讨论】:

      • 您的答案与其他答案一样,您可以编辑其中一个并将其删除。像我这样的未来读者会感谢你的清晰;)
      【解决方案5】:

      就我而言,我弄乱了UNION ALL 顶部和底部子句中的列顺序。事实证明,varchar 列出现在int 列的“下方”。一个容易犯的错误是你有很多列

      【讨论】:

        【解决方案6】:

        我会推荐使用 nvarchar(max)

        WITH CTE AS (
        SELECT x,x_name FROM (VALUES (1,CAST('' AS nvarchar(MAX)))) AS     test(x,x_name)
        UNION ALL
        SELECT x + 1 x, CONCAT(x_name,x+1)  FROM CTE WHERE x < 10 )
        SELECT * FROM CTE
        

        【讨论】:

          【解决方案7】:

          如果在一个rcte的递归项中使用CONCAT,由于concat的输出类型是varchar(MAX),所以只需要在初始查询中强制转换列即可:

          WITH rcte AS (
              SELECT 1 AS nr, CAST('1' AS varchar(MAX)) AS trail
              UNION ALL
              SELECT nr+1, CONCAT(trail, '/', nr+1)
              FROM rcte
              WHERE nr < 5
          )
          SELECT * FROM rcte;
          

          【讨论】:

            【解决方案8】:
            WITH rcte AS (
                SELECT 1 AS nr, CAST('1' AS varchar(MAX)) AS trail
                UNION ALL
                SELECT nr+1, cast(CONCAT(trail, '/', nr+1) as varchar(max))
                FROM rcte
                WHERE nr < 5
            )
            SELECT * FROM rcte;
            

            【讨论】:

            • 不要发布仅代码的答案,请解释上下文将如何帮助..
            • 这将给出上述输出而没有任何错误。就好像你将执行上面的查询一样,它会给你 sql 错误。因此我使用了强制转换函数使其无错误
            【解决方案9】:
            ;with tmp1(NewsId,DataItem ,HeaderText)
             as
              (
            
                select NewsId, LEFT(HeaderText, CHARINDEX(',',HeaderText+',')-1),
                STUFF(HeaderText, 1, CHARINDEX(',',HeaderText+','), '') 
                from Currentnews
            
                union all
            
                select NewsId, LEFT(HeaderText, CHARINDEX(',',HeaderText+',')-1),
                STUFF(HeaderText, 1, CHARINDEX(',',HeaderText+','), '')
                from tmp1
                where HeaderText > ''
            
               )
            
               select NewsId, DataItem
               from tmp1
               order by NewsId
            

            【讨论】:

            • 如果没有正确的格式,这是不可能阅读的。见How do I format my code blocks
            • 可能他是个新手(:我也曾一度
            • 我一直在使用您提供的确切查询,但它仍然给我与问题状态相同的错误。
            猜你喜欢
            • 2019-05-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-09-11
            • 2014-07-13
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多