所以我正在创建一个存储过程,其最终目标是动态ETL解决方案。我的公司处理很多第三方数据,而且我经常不知道列的数量,数据类型,数据的格式等等......因此,我把一些带有动态的临时表放在一起sql和bulk insert语句将数据导入SQL Server。目前,数据作为单个列nvarchar字段,以制表符或管道分隔,并且每个txt或csv文件通常超过100k行。上述csv / txt格式的一个例子如下:
RawSingleLine
9XX01 No Cancelled Inadvertent Approval 1/12/2015 432115.2 99
480X1 No Cancelled Pending Processing 1/7/2014 5060 27.5
我目前的解决方案是使用游标和下面的Split函数循环遍历所有单行,拆分它们,转动它们,然后插入我的一个动态临时表中。但是,我想避免使用游标,因为它们很昂贵,并且首选基于集合的操作。
CREATE FUNCTION [dbo].[udf_Split]
(
@String NVARCHAR(4000),
@Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
WITH Split(stpos,endpos)
AS(
SELECT 0 AS stpos, CHARINDEX(@Delimiter,@String) AS endpos
UNION ALL
SELECT endpos+1, CHARINDEX(@Delimiter,@String,endpos+1)
FROM Split
WHERE endpos > 0
)
SELECT 'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
'Data' = SUBSTRING(@String,stpos,COALESCE(NULLIF(endpos,0),LEN(@String)+1)-stpos)
FROM Split
)
有没有办法在没有光标的情况下实现我想要的东西?
答案 0 :(得分:0)
免责声明:我是该项目的所有者Eval SQL.NET
此解决方案允许在大约2-3秒内拆分和旋转100k行。 Eval SQL.NET允许在T-SQL中执行C#代码。
-- CREATE a big string with all the rows (100,000 rows)
DECLARE @s VARCHAR(MAX) = ''
SET @s = ( SELECT TOP ( 100000 )
RawSingleLine + CHAR(13) + CHAR(10)
FROM Import
FOR XML PATH('') ,
TYPE
).value('text()[1]', 'varchar(max)')
-- Use C# Syntax to split the text. Use Regex.Split if necessary.
DECLARE @sqlnet SQLNET = SQLNET::New('
var rows = s.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
return rows.Select(x => x.Split('' '')).ToList()
').ValueString('s', @s).AutoDispose()
EXEC dbo.SQLNET_EvalResultSet @sqlnet