【问题标题】:SQL Server CTE error: Types don't match between the anchor and the recursive partSQL Server CTE 错误:锚点和递归部分之间的类型不匹配
【发布时间】:2016-02-04 20:52:16
【问题描述】:

我编写了一个 CTE 代码,它将分隔的字符串(分隔符可以是任何东西)解析到一个表中。所以“MI,TX,WI”会被解析成一个3行的表。

只要我不使用NVARCHAR(MAX) 作为我要解析的字符串输入,它就可以工作。

我想知道如何让它与NVARCHAR(MAX)(或至少VARCHAR(MAX))一起工作?

如果您更改此错误,则除了注释之外,此方法有效:

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

--- change this to NVARCHAR(MAX) and it fails
DECLARE @DelimitedString NVARCHAR(4000) 
DECLARE @Delimiter NVARCHAR(10) 
SET @Delimiter = '--'

SET @DelimitedString= '123--456--7890, 234--456--7890'

-- do here instead of in every loop below
DECLARE @DelimiterLength AS TINYINT
SET @DelimiterLength = len(@Delimiter) 

;with cte as 
( 
    select 0 a, 1 b  
    union all 
    select b, charindex(@Delimiter, @DelimitedString, b) + len(@Delimiter)      
    from cte where b > a 
)   
select LTRIM(RTRIM(
    SUBSTRING(@DelimitedString, 
        a,                  
        case when b > @DelimiterLength then b-a-@DelimiterLength else len(@DelimitedString) - a + 1 end
    )--END SUBSTRING
))--end LTRIM/RTRIM
value         
from cte where a > 0 

我了解错误在标准中的含义,UNION 数据类型中的列必须匹配。我在这里看不到如何解决此问题。

我希望它可以处理我们需要的任何长度的字符串,因为我不知道使用是否仅限于 4000 个字符的字符串。

【问题讨论】:

  • 尝试在 cte 的上半部分将 b 转换为 int
  • 有一些比 ctes 更好的分割字符串的方法。这是一篇专门介绍各种分离器以及它们如何提高性能的整篇文章。无需在这里重新发明轮子。 sqlperformance.com/2012/07/t-sql-queries/split-strings

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


【解决方案1】:

CHARINDEX() 在与VARCHAR(MAX) 而非INT 一起使用时返回BIGINT,因此您需要锚类型也为BIGINT

;with cte as ( 
    select cast(0 as bigint) a, cast(1 as bigint) b  

【讨论】:

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