2015-09-01 40 views
1

我有一个由CRLF分隔的各种文本组成的varchar列。我需要分割这个列,每个部分运行直到下一个CRLF。然后这些子字符串需要作为新行插入一个新表(我已经创建)。带有varchar列的表是tblJobsTest,列称为Notes。新表是tblJobAppointmentNotes,由JobID和AppointmentNote组成。使用CRLF +分割变量字段+插入新表

这里是我到目前为止....

DECLARE @crlf CHAR(2) = CHAR(13) + CHAR (10) 
DECLARE @Note VARCHAR(MAX) = null 

WHILE (SELECT LEN(Notes) FROM tblJobsTest) > 0 
BEGIN 
IF CHARINDEX(@crlf,Notes) > 0 
    BEGIN 
    SET @Note = SUBSTRING(Notes, 0, CHARINDEX(@crlf,Notes)) 
    INSERT INTO tblJobAppointmentNotes (AppointmentNote) 
    VALUES (@Note) 

    Update tblJAN 
    SET tblJAN.JobID = tblJT.JobID 
    From tblJobAppointmentNotes tblJAN 
    INNER JOIN tblJobsTest tblJT ON tblJAN.JobID = tblJT.JobID 

    UPDATE tblJobsTest 
    SET Notes= SUBSTRING(Notes, LEN(@Note) + 1, LEN(Notes)) 
    END 
ELSE 
    INSERT INTO tblJobAppointmentNotes (JobID, AppointmentNote) 
    SELECT JobID, Notes FROM tblJobsTest 
END 

我遇到的问题是列名“注意”没有标识。 CHARINDEX无法查找我猜测的列,所以我认为我需要使用某种形式的CTE,因此此代码可以引用tblJobsTest中的每一行?

有没有人有任何想法?谢谢

+0

你从语句期待什么'SELECT LEN(注释)FROM tblJobsTest'作为WHILE循环的条件读取?其实际含义是:'从表'tblJobsTest'中选择字段'Notes'的内容长度,选择一个随机行'。这确实是一个奇怪的检查... – Paolo

+2

使用字符串分割函数,而不是使用while循环和charindex来做这个基于set的。看到这里的一些例子:http://sqlperformance.com/2012/07/t-sql-queries/split-strings –

+0

谢谢:)。保罗是我遇到的问题。列名称注释在分钟时不明确,我想更改此代码,以便while语句选择每行并根据varchar的长度运行代码。 – Brett

回答

0

这里你是...将其粘贴到一个空的查询窗口并执行。适应你的需要......

编辑:同样的过程,但设置为基础的方法在一个去了整整一个表来做到这一点...

DECLARE @TableWithLongText TABLE(ID INT, LongText VARCHAR(MAX)); 
DECLARE @TableToInsertParts TABLE(ID INT IDENTITY, TWLT_ID INT,PartNr INT, eachLine VARCHAR(MAX)); 


INSERT INTO @TableWithLongText VALUES 
(1,'This' + CHAR(13) + CHAR(10) + 'is the text for ID=1' + CHAR(13) + CHAR(10) + 'with' + CHAR(13) + CHAR(10) + '4 lines') 
,(2,'This' + CHAR(13) + CHAR(10) + 'is the text for ID=2' + CHAR(13) + CHAR(10) + 'with 3 lines'); 

WITH Recoded(ID,x) AS 
(
    SELECT ID 
      ,CAST('<root><r>' + REPLACE(twlt.LongText,CHAR(13)+CHAR(10),'</r><r>') + '</r></root>' AS XML) 
    FROM @TableWithLongText AS twlt 
) 
INSERT INTO @TableToInsertParts(TWLT_ID,PartNr,eachLine) 
SELECT ID 
     ,ROW_NUMBER() OVER(PARTITION BY ID ORDER BY ID) 
     ,a.b.value('.','varchar(max)') 
FROM Recoded 
CROSS APPLY Recoded.x.nodes('/root/r') a(b); 

SELECT * FROM @TableToInsertParts; 
+0

谢谢Shnugo!这工作很好,但它不能解决我的主要问题。我原来有另一个变量来代替名为@Mystring的列字段'Notes',我可以通过该变量传递每行数据,并获得与您的方法相同的结果。我遇到的问题是,有近30万条记录,我无法真正地分析每一行!有没有办法自动将变量设置为第一行数据...运行代码...然后使用第二行数据等等?所以我有效地点击执行,代码为我桌子上的每个记录运行? – Brett

+0

@布雷特:我编辑了我的例子来向你展示,你如何一次完成整个表的设置,基于集合,没有WHILE或者CURSOR或者像这样的东西... – Shnugo

+0

@Brett,你检查了我最后一次编辑吗?对你起作用吗?如果是,请投票和/或标记为接受,thx。如果不是,只是回来了更多的信息。 – Shnugo