字段值SQL Server中的分隔符

时间:2016-11-22 08:41:07

标签: sql sql-server csv delimiter

我有一个csv文件,它有超过2000万行,分隔符是垂直条。问题是文件中有一个文本列,其中还包含文本中的垂直条,这会导致数据混乱并导致列在SQL Server中导入csv文件时转移到下一个列。

文件太大而无法处理,例如如果我们想要添加限定符或使用更精细的文本编辑器更改分隔符类型。

有什么想法吗?理想情况下,这样的问题的任何一般解决方案?有时虽然您使用限定符,但可能存在包含类似限定符的字符串,分隔符等的文本字段。

未引用字段。行看起来像这样:

field1|field2|field3|field4  
1|000|some text|some text  
2|001|some text con|taining pipe|some text  
3|002|some text|some text  

2 个答案:

答案 0 :(得分:1)

访问bash(Linux / Unix / Cygwin等)

为了估计问题的严重性,请检查包含4个字段和其他字段数的记录数。

awk -F'|' '{rec[NF==4?"NF=4":"NF!=4"]++}END{for(nf in rec){print nf,rec[nf]}}' MyFile.csv

生成包含良好记录的文件并加载它。

awk -F'|' 'NF==4{print}' MyFile.csv > MyFile_good.csv

生成包含错误记录的文件,并检查是否可以手动修复或以其他方式修复(如果您识别模式)

awk -F'|' 'NF!=4{print}' MyFile.csv > MyFile_bad.csv

支持限定符

"1"|"000"|"some text"|"some text"  
"2"|"001"|"some text con|taining pipe"|"some text"  
"3"|"002"|"some text"|"some text"  

我们现在定义合格字段的外观(awk -F'|'

,而不是定义分隔符(FPAT="\"[^\"]*\"")。
awk 'BEGIN{OFS="\t";FPAT="\"[^\"]*\""}{rec[NF==4?"NF=4":"NF!=4"]++}END{for(nf in rec){print nf,rec[nf]}}' MyFile.csv

答案 1 :(得分:1)

您可以将整行导入NVARCHAR(MAX)列并通过T-SQL修复或解析

CREATE TABLE MyCSV (
    csv NVARCHAR(MAX) NULL      -- VARCHAR(MAX) NULL
)
GO

BULK INSERT   MyCSV 
FROM 'data_file' 
WITH (
    DATAFILETYPE =   'widechar' --'char' 
    ,FIELDTERMINATOR = '\r\n'
)
-- OR WITH (FORMATFILE='C:\t_floatformat-c-xml.xml'); 
GO

/*
INSERT INTO MyCSV 
VALUES 
    ('1|000|some text|some text')
    ,('2|001|some text con|taining pipe|some text')
    ,('3|002|some text|some text')
*/

ALTER TABLE MyCSV 
    ADD RowID INT NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED
GO

对于parsng,您可以使用此功能:

-- SELECT * FROM [dbo].[Split2Column] (N'1|000|some text|some text', N'|')
CREATE FUNCTION [dbo].[Split2Column] (  
    @String NVARCHAR(MAX),
    @SepColumn NCHAR(1)
)
RETURNS @Columns TABLE (
     [1] NVARCHAR(MAX)
    ,[2] NVARCHAR(MAX)
    ,[3] NVARCHAR(MAX)
    ,[4] NVARCHAR(MAX)
    ,[5] NVARCHAR(MAX)
    ,[6] NVARCHAR(MAX)
    ,[7] NVARCHAR(MAX)
    ,[8] NVARCHAR(MAX)
    ,[9] NVARCHAR(MAX)
    ,[10] NVARCHAR(MAX)
)

AS
BEGIN

    ;WITH columns (cn, n1, n2 ) AS ( 
    SELECT CAST(1 as int) as cn, CAST(0 as bigint) as n1, CHARINDEX(@SepColumn, @String + @SepColumn) as n2
    UNION ALL 
    SELECT cn + 1, n2 as n1, CHARINDEX(@SepColumn, @String + @SepColumn, n2 + 1) as n2
    FROM columns
    WHERE n2 < LEN(@String)
    )

    INSERT INTO @Columns
    SELECT [1],[2],[3],[4],[5],[6],[7],[8],[9],[10]
    FROM 
        (
        SELECT cn,
            SUBSTRING(@String, n1 + 1, n2 - n1 - 1) as val
        FROM columns) parsed
    PIVOT (
            MIN(val) FOR cn IN ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10]) 
        ) pvt
        OPTION (MAXRECURSION 0);

    RETURN;
END
GO

结果如下:

SELECT MyCSV.RowID
    ,[Split2Column].*
FROM MyCSV
    CROSS APPLY [dbo].[Split2Column] (MyCSV.csv, N'|')
--WHERE [Split2Column].[5] IS NOT NULL
ORDER BY MyCSV.RowID

RowID   1   2   3               4               5           6       7       8       9       10
1       1   000 some text       some text       NULL        NULL    NULL    NULL    NULL    NULL
2       2   001 some text con   taining pipe    some text   NULL    NULL    NULL    NULL    NULL
3       3   002 some text       some text       NULL        NULL    NULL    NULL    NULL    NULL