选择Pipe delimited String作为表行

时间:2013-12-31 00:24:54

标签: sql-server

我有一个包含分隔字符串数据的表,

ColumnX

A|B|C|D|E|
F|G|H|I|K|
1|2|3|4|5|
6|7|8|9|10|

寻找像

这样的输出
col1 col2 col2 col4 col5
A    B    C    D    E
F    G    H    I    K
1    2    3    4    5
6    7    8    9    10

在某些情况下,分隔的字符串有106个管道(|)分隔值。需要帮助才能有一个select语句,可以将分隔的字符串展平为要插入临时表的行。请指教......

目前,我们正在为每一行生成select语句并批量插入表中,这需要花费2个小时的时间来完成500000条记录。

2 个答案:

答案 0 :(得分:1)

测试数据

DECLARE @t TABLE (Data NVARCHAR(1000))

INSERT INTO @t
VALUES 
('A|B|C|D|E|F|G|H|I|K'),
('F|G|H|I|K|L|3|4|5|11'),
('1|2|3|4|5|11|7|8|9|10|13'),
('6|7|8|9|10|13|E|F|G|H|I|K')

<强>查询

;WITH Split_Fields (Field, xmlfields)
AS
(
    SELECT Data AS Field,
    CONVERT(XML,'<Fields><field>'  
    + REPLACE(Data,'|', '</field><field>') + '</field></Fields>') AS xmlfields
      FROM @t
)

 SELECT       
 xmlfields.value('/Fields[1]/field[1]','varchar(100)') AS Column1,    
 xmlfields.value('/Fields[1]/field[2]','varchar(100)') AS Column2,
 xmlfields.value('/Fields[1]/field[3]','varchar(100)') AS Column3,    
 xmlfields.value('/Fields[1]/field[4]','varchar(100)') AS Column4,
 xmlfields.value('/Fields[1]/field[5]','varchar(100)') AS Column5,
 xmlfields.value('/Fields[1]/field[6]','varchar(100)') AS Column6,
 xmlfields.value('/Fields[1]/field[7]','varchar(100)') AS Column7,
 xmlfields.value('/Fields[1]/field[8]','varchar(100)') AS Column8,
 xmlfields.value('/Fields[1]/field[9]','varchar(100)') AS Column9,
 xmlfields.value('/Fields[1]/field[10]','varchar(100)') AS Column10
 FROM Split_Fields

结果集

╔═════════╦═════════╦═════════╦═════════╦═════════╦═════════╦═════════╦═════════╦═════════╦══════════╗
║ Column1 ║ Column2 ║ Column3 ║ Column4 ║ Column5 ║ Column6 ║ Column7 ║ Column8 ║ Column9 ║ Column10 ║
╠═════════╬═════════╬═════════╬═════════╬═════════╬═════════╬═════════╬═════════╬═════════╬══════════╣
║ A       ║ B       ║ C       ║ D       ║ E       ║ F       ║ G       ║ H       ║ I       ║ K        ║
║ F       ║ G       ║ H       ║ I       ║ K       ║ L       ║ 3       ║ 4       ║ 5       ║ 11       ║
║ 1       ║ 2       ║ 3       ║ 4       ║ 5       ║ 11      ║ 7       ║ 8       ║ 9       ║ 10       ║
║ 6       ║ 7       ║ 8       ║ 9       ║ 10      ║ 13      ║ E       ║ F       ║ G       ║ H        ║
╚═════════╩═════════╩═════════╩═════════╩═════════╩═════════╩═════════╩═════════╩═════════╩══════════╝

答案 1 :(得分:0)

目前,这是我采取的方法,在大约30分钟内执行500个事务的插入,包含106列:代码基本上生成100个插入语句,每个批处理TABLOCK选项,从表中读取500000个分隔字符串,并插入到目的地。

set @sql_temp=N'
declare @BatchSize int
declare @BatchCounter int
declare @TotalRecordCount int
declare @strBatchSQL nvarchar(max)
SET @BatchSize = 100
SET @BatchCounter = 0 
set @TotalRecordCount = '+cast(@recordcount as varchar(50))+'
SET @strBatchSQL=null
while @BatchCounter < (@TotalRecordCount/@BatchSize) + 1
begin
SET @strBatchSQL =STUFF(
(
  SELECT CAST('''' AS NVARCHAR(MAX)) + RTRIM(LTRIM(DelimitedFields))
  FROM (
SELECT Row_Line,DelimitedFields,_Record_Id FROM (
SELECT 
  row_number() OVER(ORDER BY _Record_ID) AS Row_Line,Record_Id,Import_Sequence_Number,
''INSERT INTO '+ SUBSTRING(@YourTable,1,LEN(@YourTable)-1) +'_FLAT_TMP] WITH (TABLOCK) VALUES (''''''+ convert(varchar(20),rank() OVER (ORDER BY Record_Id))+'''''',''''N'''','''''+@LoadSpecificId+''''',''''N'''',''''''+Cast(Import_Sequence_Number as VarChar(100))+'''''',''+'''''''' + CAST(Record_ID AS VARCHAR (100)) + '''''','''''' + replace(record_string,''|'', '''''','''''') + '''''');'' AS DelimitedFields
FROM ' + @YourTable + ' WHERE Record_Id BETWEEN '+cast(@minrecordID as varchar(50))+' and '+cast(@maxrecordID as varchar(50))+'  ) TabAlias
WHERE TabAlias.Row_Line > (@BatchSize * @BatchCounter )  
         AND   TabAlias.Row_Line <=  ((@BatchSize * @BatchCounter)+ @BatchSize)  
) AS a 
FOR XML PATH('''')
), 1,0, '''')  
EXEC SP_EXECUTESQL @strBatchSQL     
set @BatchCounter = @BatchCounter + 1               
end'

EXEC SP_EXECUTESQL @sql_temp