CTE 从锚点和递归部分触发投射错误

CTE triggers casting error from anchor and recursive part

我有一个 CTE,实际上是从 VSTS 数据中找到所有工作项及其 parents。

;with cte(wtype,id,parent,title,ptype,WILevel,ParentTitle) as
(
select WorkItemType,wi_id,parent,title,ParentType,0 as WILevel,'' as ParentTitle from tbl_VSTS_AllWorkItems where Parent is null and state<>'Removed'
union all
select WorkItemType,wi_id,W.parent,W.title,ParentType=t2.wtype,(t2.WILevel+1) as WILevel, t2.title as ParentTitle  from tbl_VSTS_AllWorkItems W inner join cte t2 on t2.id=W.Parent where state<>'Removed'
)

select * from cte where WILevel=0;

但是我得到如下转换错误。

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

我不明白这个问题,因为标题字段只是 varchar 类型。那么为什么类型不匹配?

union all 的第一部分中,我认为您希望在创建 '' as ParentTitle 时明确说明,以便它实际上是列的类型。例如 convert(varchar(30), null) as ParentTitle.

我自己承认,我搜索了您的错误消息并发现 this SO question 讨论了类似的问题。

这里的技巧是,即使您的两列都是文本,但它们不是同一类型的文本(例如宽度等)。

假设 tbl_VSTS_AllWorkItems.title 列是 varchar(50),您可以通过将空字符串也转换为 varchar(50) 来解决此错误,例如

WITH cte (wtype,id,parent,title,ptype,WILevel,ParentTitle) AS (
    SELECT ..., CAST('' AS varchar(50)) AS ParentTitle
    FROM tbl_VSTS_AllWorkItems
    WHERE ...
    UNION ALL
    SELECT ..., t2.title
    FROM tbl_VSTS_AllWorkItems
    WHERE ...
)

旁注:您只需要在联合查询的第一个 select 中使用别名。事实上,合并的后续部分中的别名将被忽略。