2016-11-15 122 views
3

我想從csv文件導入數據到SQL Server。在csv文件中有成千上萬的條目,我們有很多行中有不正確的數據。從csv文件批量插入 - 忽略有錯誤的行 - SQL Server

一些CSV文件中的行是:

`"ID"|"EmpID"|"FName"|"LName"|"Gender"|"DateOfBirth" 
"1"|"90043041961"|"ABCD"|"TEST"|"F"|"1848-05-05 00:00:00.000" 
"1"|"10010161961"|"XYZ"|"TEST"|"F"|"1888-12-12 00:00:00.000" 
. 
. 
.. 
.. 
.... 
"4"|"75101141821PPKKLL"|"LLKK"|"F"|"1925-09-09 00:00:00.000"|"" 
"4"|"32041401961UUYYTT"|"PPLL"|"M"|"1920-01-01 00:00:00.000"|"" 
. 
..... 
"25"|"00468132034"|"FGTT"|"OOOO"|"F"|"1922-11-11 00:00:00.000" 
"25"|"00468132034"|"KKKK"|"PPPP"|"F"|"1922-11-11 00:00:00.000" 

創建TestTable的,並試圖插入數據(來自CSV文件)到它:

create table TestTable 
(
    ID varchar(5), 
    EmpID varchar(25), 
    FName varchar(25), 
    LName varchar(25), 
    Gender varchar(5), 
    DateOfirthB varchar(30) 
); 

我使用下面的腳本從csv文件中的SQL Server數據導入TestTable

bulk insert TestTable 
from 'C:\TestData.csv' 
with 
    (firstrow = 2, 
    DATAFILETYPE='char', 
    FIELDTERMINATOR= '"|"', 
    ROWTERMINATOR = '\n', 
    ERRORFILE ='C:\ImportErrors.csv', 
    MAXERRORS = 0, 
    TABLOCK 
    ); 

錯誤:

消息4863,級別16,狀態1,行1
爲32763行批量負載數據轉換錯誤(截斷),第5列(性別)。

Msg 4863,Level 16,State 1,Line 1
Row 32764,列5(性別)的批量加載數據轉換錯誤(截斷)。

是否有任何方法可以忽略行(在csv文件中)由於某些原因或其他原因無法添加的行並插入具有正確語法的行?

感謝

PS:我不能使用SSIS。只允許使用SQL

+0

我知道這並不能回答你的問題,但老實說,我認爲你會更好嘗試使用SSIS做到這一點,而不是原始的SQL – DForck42

+0

@ DForck42 - 我希望我能使用SSIS但可以不。我只能用這個SQL ...感謝您的建議 –

+1

通常的過程是首先將數據導入更寬容的臨時表(即所有字段都是NVARCHAR(4000))。然後使用SQL來清理並將數據移動到最終表中。我個人更喜歡這種方法自己的SSIS –

回答

2

我處理不同來源的CSV文件,每週收到不同的CSV文件,所以數據非常乾淨,而其他人則是噩夢。所以這就是我如何處理我收到的CSV字段,我希望它可以幫助你。您仍然需要添加一些數據驗證來處理格式錯誤的數據。

SET NOCOUNT ON 
GO 

-- Create Staging Table 
    IF OBJECT_ID(N'TempDB..#ImportData', N'U') IS NOT NULL 
     DROP TABLE #ImportData 

    CREATE TABLE #ImportData(CSV NVARCHAR(MAX)) 

-- Insert the CSV Data 
    BULK INSERT #ImportData 
     FROM 'C:\TestData.csv' 

-- Add Control Columns 
    ALTER TABLE #ImportData 
     ADD ID INT IDENTITY(1, 1) 

    ALTER TABLE #ImportData 
     ADD Malformed BIT DEFAULT(0) 

-- Declare Variables 
    DECLARE @Deliminator NVARCHAR(5) = '|', @ID INT = 0, @DDL NVARCHAR(MAX) 
    DECLARE @NumberCols INT = (SELECT LEN(CSV) - LEN(REPLACE(CSV, @Deliminator, '')) FROM #ImportData WHERE ID = 1) 

-- Flag Malformed Rows 
    UPDATE #ImportData 
     SET Malformed = CASE WHEN LEN(CSV) - LEN(REPLACE(CSV, @Deliminator, '')) != @NumberCols THEN 1 ELSE 0 END 

-- Create Second Staging Table 
    IF OBJECT_ID(N'TestTable', N'U') IS NOT NULL 
     DROP TABLE TestTable 

    CREATE table TestTable 
     (ID varchar(4000), 
     EmpID varchar(4000), 
     FName varchar(4000), 
     LName varchar(4000), 
     Gender varchar(4000), 
     DateOfirthB varchar(4000)); 

-- Insert CSV Rows 
    WHILE(1 = 1) 
     BEGIN 
      SELECT TOP 1 
       @ID = ID 
       ,@DDL = 'INSERT INTO TestTable(ID, EmpID, FName, LName, Gender, DateOfirthB)' + CHAR(13) + CHAR(10) + REPLICATE(CHAR(9), 1) 
          + 'VALUES' -- + CHAR(13) + CHAR(10) + REPLICATE(CHAR(9), 2) 
            + '(' + DDL + ')' 
      FROM 
       (
        SELECT 
         ID 
         ,DDL = '''' + REPLACE(REPLACE(REPLACE(CSV, '''', ''''''), @Deliminator, ''','''), '"', '') + '''' 
        FROM 
         #ImportData 
        WHERE 
         ID > 1 
         AND Malformed = 0) D 
      WHERE 
       ID > @ID 
      ORDER BY 
       ID 

      IF @@ROWCOUNT = 0 BREAK 

      EXEC sp_executesql @DDL 
     END 

-- Clean Up 
    IF OBJECT_ID(N'TempDB..#ImportData', N'U') IS NOT NULL 
     DROP TABLE #ImportData 

-- View Results 
    SELECT * FROM dbo.TestTable 
+2

psst:它不是'@ Deliminator'的'@ Delimiter'。但無論如何真棒腳本。 –

+1

我故意拼錯在我發佈的代碼中的單詞,這種方式如果我看到它發佈在其他網站上,我知道它來自何處;-),謝謝! –

+1

@MarkKram - 非常感謝 –