SQL Server存储过程循环逗号分隔列表

时间:2015-10-10 11:28:21

标签: sql-server stored-procedures

是否可以创建一个存储过程来拆分逗号分隔列表然后遍历列表并执行更新语句?

这只是3个更新语句的3次更新,这些更新语句在120,000个字符长的区域内,并发执行:

UPDATE OPERATION 
SET START = '20151012', FINISH = '20151012' 
WHERE REF = '912^0^15'; 

UPDATE OPERATION 
SET START = '20151012', FINISH = '20151013' 
WHERE REF = '913^0^15'; 

UPDATE OPERATION 
SET START = '20151013', FINISH = '20151014' 
WHERE REF = '872^0^15'; 

我想的是,将一个列表传递给一个过程,然后让它创建更新语句,从而将每个更新的长度从每个记录的111个字符减少到大约30个字符。

我不知道如何在SQL Server中编写存储过程,但在javascript中我会这样做:

伪代码:

list = "'20151012','20151012','912^0^15'|'20151012', '20151013','913^0^15'|'20151013','20151014','872^0^15'"

for each list.split('|') as row
    cols = row.split(',')

    UPDATE OPERATION  
    SET START = 'cols[0]', FINISH = 'cols[1]' 
    WHERE REF = 'cols[2]';      

是否可以创建可以执行此操作的存储过程?

2 个答案:

答案 0 :(得分:0)

我根本不喜欢你的想法。但为了证明我有可能准备了小型演示:

<强> LiveDemo

DECLARE @string NVARCHAR(MAX) = 
 '20151012,20151012,912^0^15|20151012, 20151013,913^0^15|20151013,20151014,872^0^15';

CREATE TABLE #OPERATION(START NVARCHAR(100), FINISH NVARCHAR(100), REF NVARCHAR(100));

INSERT INTO #OPERATION 
VALUES ('', '', '912^0^15'),
       ('', '', '913^0^15'),
       ('', '', '872^0^15');


WITH cte AS
(
SELECT  
xml_data = CAST(REPLACE(REPLACE('<d>'+REPLACE(REPLACE(@string,'|','</d><d>'), ',' ,'</e><e>') +'</d>', '</d>', '</e></d>'), '<d>', '<d><e>') AS XML)
) , cte2 AS (
SELECT record.r.value('e[1]', 'NVARCHAR(100)') AS [start],
       record.r.value('e[2]', 'NVARCHAR(100)') AS [finish],
       record.r.value('e[3]', 'NVARCHAR(100)') AS [ref]
FROM cte
CROSS APPLY xml_data.nodes('//d') AS record(r)
)
UPDATE o
SET Start  = c.[start]
   ,finish = c.[finish]
FROM #OPERATION o
JOIN cte2 c
  ON c.ref = o.ref;

SELECT *
FROM #Operation;

您可以使用@string为参数的存储过程将其包装。

<强> StoredProcedureDemo

CREATE PROCEDURE dbo.my_custom_update
  @string NVARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;

WITH cte AS
(
SELECT  
xml_data = CAST(REPLACE(REPLACE('<d>'+REPLACE(REPLACE(@string,'|','</d><d>'), ',' ,'</e><e>') +'</d>', '</d>', '</e></d>'), '<d>', '<d><e>') AS XML)
) , cte2 AS (
SELECT record.r.value('e[1]', 'NVARCHAR(100)') AS [start],
       record.r.value('e[2]', 'NVARCHAR(100)') AS [finish],
       record.r.value('e[3]', 'NVARCHAR(100)') AS [ref]
FROM cte
CROSS APPLY xml_data.nodes('//d') AS record(r)
)
UPDATE o
SET Start  = c.[start]
   ,finish = c.[finish]
FROM OPERATION o
JOIN cte2 c
  ON c.ref = o.ref;

END;
GO

答案 1 :(得分:0)

尝试使用像这样的XML

DECLARE     @list VARCHAR(MAX) = '''20151012'',''20151012'',''912^0^15''|''20151012'', ''20151013'',''913^0^15''|''20151013'',''20151014'',''872^0^15'''

SELECT      s.rowno
            , MAX(CASE WHEN s.colno = 1 THEN s.value END) AS start
            , MAX(CASE WHEN s.colno = 2 THEN s.value END) AS finish
            , MAX(CASE WHEN s.colno = 3 THEN s.value END) AS ref
FROM        (
            SELECT      c.rowno
                        , ROW_NUMBER() OVER (PARTITION BY c.rowno ORDER BY (SELECT 1))
                        , REPLACE(LTRIM(d.x.value('(./text())[1]', 'VARCHAR(MAX)')), '''', '')
            FROM        (
                        SELECT      ROW_NUMBER() OVER (ORDER BY (SELECT 1))
                                    , CONVERT(XML, '<i>' + REPLACE(b.x.value('(./text())[1]', 'VARCHAR(MAX)'), ',', '</i><i>') + '</i>')
                        FROM        ( 
                                    SELECT      CONVERT(XML, '<i>' + REPLACE(@list, '|', '</i><i>') + '</i>')
                                    ) a(x)
                        CROSS APPLY a.x.nodes('i') b(x)
                        ) c(rowno, x)
            CROSS APPLY c.x.nodes('i') d(x)
            ) s(rowno, colno, value)
GROUP BY    s.rowno