【问题标题】:"Types don't match between the anchor and the recursive part" after casting投射后“锚点和递归部分之间的类型不匹配”
【发布时间】:2020-09-29 20:55:54
【问题描述】:

在 SQL Server 存储过程中,此 CTE 正在运行。问题的总结是查询没有显式强制转换,但是即使添加了它们,SQL Server 仍然会抛出:

递归查询“ABC”的“FName”列中的锚点和递归部分的类型不匹配。

我尝试了多种类型的转换,例如使用 varchar(8000) 并将 CASE 语句包装在转换表达式中。

;WITH ABC (FId, FName) AS
(
    SELECT cast(1 as int), CAST('' AS varchar(max))
    UNION ALL
    SELECT
        cast(B.FId + 1 as int),
        CASE WHEN LEN(B.FName) > 0
            THEN cast((B.FName + ':' +  A.FName) as varchar(max))
            ELSE cast(A.FName as varchar(max))
        END
    FROM (
        SELECT
            Row_Number() OVER (ORDER BY FId) AS RN,
            FName
        FROM #T1
    ) A 
    INNER JOIN ABC B ON A.RN = B.FId AND A.RN <= 5
)

可在上下文中执行:

CREATE TABLE #T1
(
    FId     INT
,   FName   VARCHAR(max)
)

INSERT INTO #T1 VALUES
(1, '5 Oct 2020'),
(2, '12 Oct 2020'),
(3, '19 Oct 2020'),
(4, '26 Oct 2020'),
(5, '2 Nov 2020'),
(6, '9 Nov 2020'),
(7, '16 Nov 2020'),
(8, '23 Nov 2020'),
(9, '30 Nov 2020'),
(10,'7 Dec 2020'),
(11,'14 Dec 2020')

;WITH ABC (FId, FName) AS
(
    SELECT cast(1 as int), CAST('' AS varchar(max))
    UNION ALL
    SELECT
        cast(B.FId + 1 as int),
        CASE WHEN LEN(B.FName) > 0
            THEN cast((B.FName + ':' +  A.FName) as varchar(max))
            ELSE cast(A.FName as varchar(max))
        END
    FROM (
        SELECT
            Row_Number() OVER (ORDER BY FId) AS RN,
            FName
        FROM #T1
    ) A 
    INNER JOIN ABC B ON A.RN = B.FId AND A.RN <= 5
) SELECT * FROM ABC

【问题讨论】:

  • minimal reproducible example 将帮助我们帮助您。
  • @Larnu 我稍后会添加它。谢谢。
  • 您提供的 SQL 没有复制问题 (db<>fiddle)。我们需要一个满足复制部分的minimal reproducible example
  • 所以您是说数据库的默认排序规则与 tempDb 的默认排序规则不同?
  • @shnugo 如果该列是用特定的排序规则声明的,那会更明显......荣誉!

标签: sql sql-server tsql


【解决方案1】:

对于递归 CTE,输入非常挑剔,尤其是字符串。

不同行为的原因似乎是您的服务器和列的(默认)排序规则不同。

试试这个:

;WITH ABC (FId, FName) AS
(
    SELECT cast(1 as int), CAST('' AS varchar(max)) COLLATE DATABASE_DEFAULT
    UNION ALL
    SELECT
        cast(B.FId + 1 as int),
        CAST(CASE WHEN LEN(B.FName) > 0
            THEN B.FName + ':' +  A.FName
            ELSE A.FName END as varchar(max)) COLLATE DATABASE_DEFAULT --I use one cast for the whole CASE expression
    FROM (
        SELECT
            Row_Number() OVER (ORDER BY FId) AS RN,
            FName
        FROM #T1
    ) A 
    INNER JOIN ABC B ON A.RN = B.FId AND A.RN <= 5
) SELECT * FROM ABC

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-01
    • 2010-12-22
    • 2018-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-13
    相关资源
    最近更新 更多