2017-04-17 48 views
0

有一个表中所包括的IDNotes,LEN(注),和LEN/60SQL服务器:拆分文本字段成基于LEN规则多行

我需要它分解成LEN = 60块,添加一个新的“LINE”列,每行增加1。

所以:

1 | Super long text of 150 characters | 150 | 3 

变为:

- 1 | 1 | Super long text of 150 
- 1 | 2 | characters is much more 
- 1 | 3 | manageable! 

我创建了LEN和LEN/60数据的情况下,段值将是某种形式的循环语句非常有用。

递归CTE,循环,变量 - 在这一点上,我对任何事情都是开放的!

感谢您的帮助!

+3

恕我直言,你正在使数据存储和数据检索比他们需要更难。 SQL服务器可以处理长文本,并且如果它全部在一个记录中,在应用程序中读取和解析它会容易得多。 –

+0

完全同意你,仁 - 不幸的是,应用程序正在推动这个解决方案,因为它是为了处理多行项目,每行长度不超过60个字符。 – chaseman1973

回答

1

是的。 CTE是答案。请试试这个。

WITH cte_base AS(SELECT ID 
        , 1 AS IDLN 
        , LTRIM(RTRIM(Notes)) AS Notes 
        , 1 AS Rownum 
       FROM yourtable 
), cte_re AS (SELECT Id 
        , IDLN 
        , 1 AS StartPos 
        , CAST(60 - CHARINDEX(' ', REVERSE(LEFT(SUBSTRING(Notes, 1, 60) + ' ', 60))) AS INT) StringLen 
       FROM cte_base 
       WHERE Rownum =1 
       UNION ALL 
       SELECT r.Id 
        , r.IDLN + 1 
        , StartPos + StringLen + 1 
        , CAST(60 - CHARINDEX(' ', REVERSE(LEFT(SUBSTRING(b.Notes, StartPos + StringLen + 1, 60) + ' ', 60))) AS INT) 
       FROM CTE_re r 
       INNER JOIN cte_base b 
        ON b.Id = r.Id and b.rownum = 1 
       WHERE StartPos + StringLen <= DATALENGTH(b.Notes) 
)  
SELECT r.Id 
    , r.IDLN 
    , UPPER(SUBSTRING(b.Notes, r.StartPos, r.StringLen)) AS Notes 
FROM cte_re r 
INNER JOIN cte_base b 
ON r.Id = b.Id; 
+0

非常感谢,温迪!这是SUPER关闭,但我遇到了两个问题: 1:任何超过1段的行都会产生额外的“空白”行。因此,ID为1771的长度为110的应该导致2行(IDLN 1和2),但结果为4,最后2个空白注释值为 2:如果我让您的代码在未指定ID的情况下运行,则会收到Msg 530,“最大递归100在语句完成之前已经耗尽”错误。 你能帮助我多一点吗? – chaseman1973

+0

你能提供一些样本数据吗? – Wendy