TSQL如何在解析行时迭代行?

时间:2010-08-01 17:30:12

标签: sql sql-server tsql stored-procedures parsing

很抱歉这个问题措辞不好我不知道如何形容这个。我想迭代遍历表中的每一行,同时这样做,提取一个列,解析其中的varchar,并根据它找到的行插入到另一个表中。有点像这样:

DECLARE @string varchar(max);
foreach row in (select * from Table) {
    set @string = row[column];
    while (len(@string) > 0) {
        -- Do all the parsing in here

        if (found what was looking for)
            insert into Table2 values(row[column2], row[column3]);
    }
}

将它作为存储过程非常好,以便在SQL中完成。我不太确定如何处理它。感谢。

编辑:

这基本上是我希望的功能:

Table 1   |
id_number | text    |
1           Hello, test 532. Yay oh and test 111   
2           test 932.
3           This is a test 315 of stuff test 555.
4           haflksdhfal test 311 sadjhfalsd
5           Yay.

我想通过这个表并解析所有文本列以查找'test#'的实例,其中#是一个数字。当它以该格式在文本中找到某些内容时,它会将该值插入另一个表中,如:

Table 2   |
id_number | number
1           532
1           111
2           932
3           315
3           555
4           311

6 个答案:

答案 0 :(得分:5)

您正在考虑程序而不是基于集合。你可以将整个事情写成一个查询:

INSERT INTO target_table (column list)
SELECT (column list)
FROM source_table
WHERE (parse your column) = (some criterion)

写起来要容易得多,也可能更快。

如果您的解析功能很复杂,您可以将其放入用户定义的函数中,而不是直接将其嵌入到查询中。

答案 1 :(得分:3)

在SQL Server 2008中,您可以执行此操作

WITH testTable AS
(
SELECT 1 AS id_number, N'Hello, test 532. Yay oh and test 111' AS txt UNION ALL
SELECT 2, N'test 932.' UNION ALL
SELECT 3, N'This is a test 315 of stuff test 555.' UNION ALL
SELECT 4, N'haflksdhfal test 311 sadjhfalsd' UNION ALL
SELECT 5, N'Yay.'
)

SELECT id_number,display_term
FROM testTable
CROSS APPLY sys.dm_fts_parser('"' + REPLACE(txt,'"','""') + '"', 1033, 0,0)
WHERE TXT IS NOT NULL and 
  display_term NOT LIKE '%[^0-9]%' /*Or use LIKE '[0-9][0-9][0-9]' to only get 3 
                                     digit numbers*/

返回

id_number   display_term
----------- ------------------------------
1           532
1           111
2           932
3           315
3           555
4           311

答案 2 :(得分:2)

这样的事情你总是有“测试(数字)”。它适用于SQL Server 2005 +

DECLARE @Table1 TABLE (id_number int, textcol nvarchar(MAX))

INSERT @Table1 VALUES (1, 'Hello, test 532. Yay oh and test 111')
INSERT @Table1 VALUES (2, 'test 932.')
INSERT @Table1 VALUES (3, 'This is a test 315 of stuff test 555.')
INSERT @Table1 VALUES (4, 'haflksdhfal test 311 sadjhfalsd')
INSERT @Table1 VALUES (5, 'Yay.')


;WITH cte AS
(
    SELECT TOP 9999 CAST(ROW_NUMBER() OVER (ORDER BY c1.OBJECT_ID) AS varchar(6)) AS TestNum
    FROM sys.columns c1 CROSS JOIN sys.columns c2
)
SELECT id_number, TestNum FROM
    cte
    JOIN
    @Table1 ON PATINDEX('%Test ' + TestNum + '[^0-9]%', textcol) > 0
                    OR textcol LIKE '%Test ' + TestNum
ORDER BY
    id_number

答案 3 :(得分:1)

您正在寻找的功能称为CURSOR - here是一篇关于如何使用它们的文章。

它们被认为对性能有害并且难以正确使用。

重新思考你的问题并重申它,以便在基于集合的操作中解决它。

请查看使用table variablessub queries表示您的复杂情况。

答案 4 :(得分:0)

您正在使用光标 - 请参阅MSDN文档here。请注意,应尽可能避免使用游标 - 很少有地方可以使用它们,并且可能会导致代码效率低下 - 通常情况下,尝试使用基于集合的解决方案会更好。

答案 5 :(得分:0)

要按照您的要求执行此操作,可以使用Cursor进行迭代,使用下面的示例信息是光标的布局方式。您将逐行处理放在我的评论所在的位置。

DECLARE @CurrentRecord VARCHAR(MAX)

DECLARE db_cursor CURSOR FOR  
SELECT Column
FROM Table 

OPEN db_cursor   
FETCH NEXT FROM db_cursor INTO @CurrentRecord

WHILE @@FETCH_STATUS = 0   
BEGIN   
       --Your stuff here

       FETCH NEXT FROM db_cursor INTO @name   
END   

CLOSE db_cursor   
DEALLOCATE db_cursor

但是,取决于你在做什么,以及这是你经常做的事情。我建议您查看是否可以将解析提取到用户定义函数,然后您可以将其设置为基础,而不是使用游标。因为光标应该是“最后的努力”。