2010-08-23 79 views
5

我還是習慣了SQL,所以在開始使用存儲過程之前,我想先了解如何有效地使用BULK INSERT。如何使用附加列顯示文件名進行BULK INSERT?

我需要合併50個csv文件並將它們轉儲到SQL表中。問題是,我希望能夠區分每個記錄(如每個記錄屬於某個csv文件,我將通過文件名識別)。

這裏有我想要的一個小例子:

CREATE TABLE ResultsDump 
(
    PC FLOAT, 
    Amp VARCHAR(50), 
    RCS VARCHAR(50), 
    CW VARCHAR(50), 
    State0 VARCHAR(50), 
    State1 VARCHAR(50), 
) 
BULK INSERT ResultsDump 
    FROM 'c:\distance1000_7_13_2010_1_13PM_Avery DennisonAD_2300008_10S_Lock.csv' 
    WITH 
    ( 
     FIRSTROW = 2, 
     MAXERRORS = 0, 
     FIELDTERMINATOR = ',', 
     ROWTERMINATOR = '\n' 
    ) 
BULK INSERT ResultsDump 
    FROM 'c:\distance1000_7_13_2010_2_27PM_Avery DennisonAD_2300009_10S_Lock.csv' 
    WITH 
    ( 
     FIRSTROW = 2, 
     MAXERRORS = 0, 
     FIELDTERMINATOR = ',', 
     ROWTERMINATOR = '\n' 
    ) 
BULK INSERT ResultsDump 
    FROM 'C:\distance1000_7_13_2010_2_58PM_Avery DennisonAD_230000A_10S_Lock.csv' 
    WITH 
    ( 
     FIRSTROW = 2, 
     MAXERRORS = 0, 
     FIELDTERMINATOR = ',', 
     ROWTERMINATOR = '\n' 
    ) 
BULK INSERT ResultsDump 
    FROM 'c:\distance1000_7_13_2010_3_21PM_Avery DennisonAD_230000B_10S_Lock.csv' 
    WITH 
    ( 
     FIRSTROW = 2, 
     MAXERRORS = 0, 
     FIELDTERMINATOR = ',', 
     ROWTERMINATOR = '\n' 
    ) 
BULK INSERT ResultsDump 
    FROM 'c:\distance1000_7_13_2010_3_41PM_Avery DennisonAD_230000C_10S_Lock.csv' 
    WITH 
    ( 
     FIRSTROW = 2, 
     MAXERRORS = 0, 
     FIELDTERMINATOR = ',', 
     ROWTERMINATOR = '\n' 
    ) 

我知道這是做事情的方式效率極低,但我絕對想弄清楚如何手工轉儲一個文件中的SQL表中格式我想在開始創建存儲過程之前。

在新表,我想是這樣的:

FileName,PC,Amp,RCS,CW,State0,State1 
c:\distance1000_7_13_2010_1_13PM_Avery DennisonAD_2300008_10S_Lock.csv, ... 
... 
... 
c:\distance1000_7_13_2010_2_27PM_Avery DennisonAD_2300009_10S_Lock.csv, ... 
... 
... 
c:\distance1000_7_13_2010_2_58PM_Avery DennisonAD_230000A_10S_Lock.csv, ... 
... 
... 

任何簡單的建議或推薦特定的功能將是巨大的!請記住,我已經習慣了SQL,如果我可以一次完成這一步,那將是非常棒的,這就是爲什麼我要從這樣一個簡單的問題開始。

提前致謝!

+0

BULK INSERT是不是一個標準的SQL語句。用正確的DBMS標記這將是明智的 - 我懷疑MS SQL Server,但我不確定。 – 2010-08-23 03:20:42

+0

正式注意。謝謝你的糾正。 – 2010-08-23 03:32:08

回答

4

您可以將列FileName varchar(max)添加到ResultsDump表中,使用新列創建表的視圖,批量插入視圖中,並且在每次插入之後,爲仍具有其默認值的列設置文件名稱null

CREATE TABLE dbo.ResultsDump 
(
    PC FLOAT, 
    Amp VARCHAR(50), 
    RCS VARCHAR(50), 
    CW VARCHAR(50), 
    State0 VARCHAR(50), 
    State1 VARCHAR(50), 
) 
GO 

ALTER TABLE dbo.ResultsDump ADD [FileName] VARCHAR(300) NULL 
GO 

CREATE VIEW dbo.vw_ResultsDump AS 
SELECT 
    PC, 
    Amp, 
    RCS, 
    CW, 
    State0, 
    State1 
FROM 
    ResultsDump 
GO 

BULK INSERT vw_ResultsDump 
    FROM 'c:\distance1000_7_13_2010_1_13PM_Avery DennisonAD_2300008_10S_Lock.csv' 
    WITH 
    ( 
     FIRSTROW = 2, 
     MAXERRORS = 0, 
     FIELDTERMINATOR = ',', 
     ROWTERMINATOR = '\n' 
    ) 

UPDATE dbo.ResultsDump 
SET [FileName] = 'c:\distance1000_7_13_2010_1_13PM_Avery DennisonAD_2300008_10S_Lock.csv' 
WHERE [FileName] IS NULL 

BULK INSERT vw_ResultsDump 
    FROM 'c:\distance1000_7_13_2010_2_27PM_Avery DennisonAD_2300009_10S_Lock.csv' 
    WITH 
    ( 
     FIRSTROW = 2, 
     MAXERRORS = 0, 
     FIELDTERMINATOR = ',', 
     ROWTERMINATOR = '\n' 
    ) 

UPDATE dbo.ResultsDump 
SET [FileName] = 'distance1000_7_13_2010_2_27PM_Avery DennisonAD_2300009_10S_Lock.csv' 
WHERE [FileName] IS NULL 
+0

但是在這種情況下,列號不一致,所以我不能使用BULK INSERT? – 2010-08-23 03:35:24

+0

@Think Blue Crew:不會批量插入忽略表格末尾的其他列嗎?如果沒有,你必須指定一個格式文件。例如,請參閱http://stackoverflow.com/questions/3526136/csv-import-in-sql-server-2008/3526237#3526237 – Andomar 2010-08-23 03:41:52

+5

@Think Blue Crew:您可以使用Andomar的答案,將FileName列添加到您的ResultsDump表,創建一個沒有* FileName列的視圖,批量插入到視圖中,然後更新原始表中的FileName列。 – 8kb 2010-08-23 04:48:47

0

試試這個,

    ALTER PROCEDURE [dbo].[ReadandUpdateFileNames_SP] 
      (
      @spRequestId NVARCHAR(50) 
      ,@LoopCounter INT =0 
      ,@MaxFIVId INT=0 
      ,@spFileName NVARCHAR(100)=NULL) 
      AS 
      BEGIN 
      SET NOCOUNT ON 
       BEGIN TRY 
        BEGIN TRAN 
        -- To read filename's from the Request Id and store it in a temp table 
         DECLARE @cmd nvarchar(500) 
         SET @cmd = 'dir D:\Input\REQUEST-'[email protected]+' /b ' 
         --PRINT @cmd 
         DECLARE @DirOutput TABLE(
             ID INT IDENTITY 
            , files varchar(500)) 

         INSERT INTO @DirOutput 
         EXEC master.dbo.xp_cmdshell @cmd 
         SELECT * FROM @DirOutput WHERE files IS NOT NULL ORDER BY ID 

         ----Read files by RequestId BEGIN 

         SELECT @LoopCounter = min(ID) , @MaxFIVId = max(ID) 
          FROM @DirOutput 

         WHILE(@LoopCounter IS NOT NULL AND @LoopCounter<@MaxFIVId) 
         BEGIN 
         -- Create temp table to store FIVItems 
          CREATE TABLE Items_TEMP 
          (
            ControlID NVARCHAR(50) 
           , UNRS_Code NUMERIC(18,0) 
           , UNRS_Code_S NUMERIC(18,0) 
           , Ordered_Quantity NUMERIC(18,3) 
           , Sent_Quantity NUMERIC(18,3) 
           , Accepted_Quantity NUMERIC(18,3) 
           , Unit_Food_Price NUMERIC(18,2) 
           , Total_Price NUMERIC(18,2) 
          ) 
         SELECT @spFileName=files FROM @DirOutput WHERE [email protected] 
          PRINT @LoopCounter 
          DECLARE @spControlId NVARCHAR(50) 
          SET @spControlId='FFO'+ Substring(@spFileName, 4, (len(@spFileName)-7)) 
          --PRINT @spControlId 
          DECLARE @sqlCmd NVARCHAR(MAX) 
          SET @sqlCmd='BULK INSERT 
          Items_TEMP 
          FROM ''D:\Input\REQUEST-'[email protected]+'\'[email protected]+''' 
          WITH(
            FIELDTERMINATOR='','' 
           , ROWTERMINATOR=''\n'' 
          )' 
          PRINT @sqlCmd 
          EXECUTE sp_executesql @sqlCmd 
          ---Add a new column to the table which is not present in the CSV 
          ALTER TABLE Items_TEMP ADD OrderId NUMERIC(18,0)NULL 
          UPDATE Items_TEMP SET [email protected],OrderId=(SELECT OrderId FROM dbo.Orders WHERE [email protected]) 
          SELECT * FROM Items_TEMP 

          --DROP FIVItems_TEMP table once CSV output generated 
          DROP TABLE Items_TEMP 


          SET @[email protected]+1 
         END 
        ----****END*** 
        COMMIT TRAN 
       END TRY 
       BEGIN CATCH 
        ROLLBACK TRAN 
        PRINT 'ROLLBACK' 
        PRINT Error_Message() 
        SELECT ERROR_LINE() AS ErrorLine; 
       END CATCH 
      SET NOCOUNT OFF 
      END 
+0

請閱讀本文[如何回答](http://stackoverflow.com/help/how-to-answer)並根據需要優化您的答案。只是發佈代碼可能不是一個好的答案。 – thewaywewere 2017-05-07 12:40:08