CTE error: Types don't match between the anchor and the recursive part
Exactly what it says:
'name1'
has a different data type to 'name' + CAST((rn+1) as varchar(255))
Try this (untested)
;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
Basically, you have to ensure the length matches too. For the recursive bit, you may have to use CAST('name' AS varchar(4))
if it fails again
TSQL CTE error ''Types don't match between the anchor and the recursive part
The info you want is all in the documentation:
When concatenating two char, varchar, binary, or varbinary expressions, the length of the resulting expression is the sum of the lengths of the two source expressions, up to 8,000 bytes.
snip ...
When comparing two expressions of the same data type but different lengths by using
UNION
,EXCEPT
, orINTERSECT
, the resulting length is the longer of the two expressions.The precision and scale of the numeric data types besides
decimal
are fixed. When an arithmetic operator has two expressions of the same type, the result has the same data type with the precision and scale defined for that type.
However, a recursive CTE is not the same as a normal UNION ALL
:
The data type of a column in the recursive member must be the same as the data type of the corresponding column in the anchor member.
So in answer to your questions:
'Hello world!'
has the data typevarchar(12)
by default.'A' + 'B'
has the data typevarchar(2)
because that is the sum length of the two data types being summed (the actual value is not relevant).n+1
is still anint
- In a recursive CTE, the data type must match exactly, so
'1'
is avarchar(1)
. If you specifyvarchar
without a length in aCAST
then you getvarchar(30)
, sotxt + ', ' + CAST(n+1 AS varchar)
isvarchar(33)
.
When you cast the anchor part to varchar(max)
, that automatically means the recursive part will be varchar(max)
also. You don't need to cast to max
, you could also cast the recursive part directly to varchar(30)
for example:
WITH CTE(n, txt) AS
(
--SELECT 1, '1' --This does not work.
SELECT 1, CAST('1' AS varchar(30)) --This does work.
--SELECT 1, CAST('1' AS varchar(1000)) --This does not work.
UNION ALL
SELECT
n+1,
CAST(CONCAT(txt, ', ', n+1) AS varchar(30))
FROM
CTE
WHERE
n < 10
)
SELECT *
FROM CTE
db<>fiddle
SQL Server CTE error: Types don't match between the anchor and the recursive part
CHARINDEX()
returns a BIGINT
when used with a VARCHAR(MAX)
rather than an INT
so you need the anchor types to also be BIGINT
:
;with cte as (
select cast(0 as bigint) a, cast(1 as bigint) b
Types don't match between the anchor and the recursive part after casting
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
CTE “Types don't match between the anchor and the recursive part”
Finally I found the problem. The database was imported with compatibility level SQL Server 2012 (110)
.
I changed it to SQL Server 2016 (130)
and now the cte works.
CTE keeps saying Type dont match between anchor and the recursive part
In a recursive CTE the types in the union all
have to match exactly. So, if you have an nvarchar(max)
in the top part of the union, the corresponding attribute in the bottom part also has to be nvarchar(max)
, not nvarchar(10)
. Same goes for decimal datatypes; a decimal(5, 3)
doesn't match a decimal(15, 3)
.
This, of course, gets more complicated when types are not immediately identifiable, especially when doing concatenations and calculations. In those cases you want to wrap the concat/calculation in a convert: CONVERT(DECIMAL(15, 3), T1.DecimalAttribute/T2.DecimalAttribute)
or CONVERT(NVARCHAR(MAX), T1.Text + T2.Text)
cte recursion error don't match between anchor
You have just few mistakes
WITH Series AS
(
SELECT CAST(-5 AS Decimal(5, 2)) AS Number
UNION ALL
SELECT CAST((number + 0.5) AS Decimal(5, 2)) AS Number
FROM Series s
WHERE s.Number <= 4.5
)
SELECT Number,
ROW_NUMBER() OVER(ORDER BY Number ASC) AS id
FROM Series
dbfiddle demo
Related Topics
Equivalent Function for Dateadd() in Oracle
Script to Kill All Connections to a Database (More Than Restricted_User Rollback)
SQL Server Trigger Insert Values from New Row into Another Table
Error: Functions in Index Expression Must Be Marked Immutable in Postgres
Which Database Design Gives Better Performance
How to Cast a String to Integer and Have 0 in Case of Error in the Cast with Postgresql
How to Create a Pivot Query in SQL Server Without Aggregate Function
How to Write a Constraint Concerning a Max Number of Rows in Postgresql
What Is the Equivalent Postgresql Syntax to Oracle's Connect by ... Start With
Best Database Field Type for a Url
Postgres Not Using Index When Index Scan Is Much Better Option
Why Do We Need Group by with Aggregate Functions
Produce Distinct Values in String_Agg