Reputation: 1778
In a SQL Server stored procedure, this CTE is being run. The summary of the problem is that the query didn't have explicit casts, but even after adding them, SQL Server still throws:
Types don't match between the anchor and the recursive part in column "FName" of recursive query "ABC".
I've tried several variations of casting, such as using varchar(8000)
and wrapping the CASE
statement in a cast expression.
;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
)
Executable with context:
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
Upvotes: 1
Views: 182
Reputation: 67311
With recursive CTEs the typing is very picky, especially with strings.
The reason for the differing behaviour seems to be a difference in your server's and the column's (default) collation.
Try something along this:
;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
Upvotes: 2