2008-10-10 107 views
3

我使用SqlBulkCopy將數據以編程方式從Excel導出到SQL Server 2005。它工作得很好,我唯一的問題是,它不保留我在Excel文件中的行序列。我沒有要排序的列,我只想按照它們出現在Excel電子表格中的順序插入記錄。如何使用SqlBulkCopy保持行順序?

我無法修改Excel文件,而必須使用我所得到的。按任何現有列進行排序會破壞序列。

請幫助。

P.S.結束將ID列插入到電子表格中,看起來像在導出/導入過程中無法保持訂單

+0

由於SQL表本質上是無序的,以什麼方式,你可以告訴大家,插入順序是不同的 - 自動增量列? – 2008-10-10 00:34:45

回答

3

我不認爲行排序是由SQL指定或保證,除非您使用「ORDER BY」子句。

由比爾·沃恩後(http://betav.com/blog/billva/2008/08/sql_server_indexing_tips_and_t.html):

使用排序:即使一個表有 一個聚集索引(存儲在物理順序 數據)時,SQL Server 並不保證除非使用了ORDER BY子句 ,否則將以該(或任何特定) 順序返回的行將爲 。

與信息的另一個鏈接:

http://sqlblogcasts.com/blogs/simons/archive/2007/08/21/What-is-the-position-of-a-row--.aspx

0

如果您可以將Excel電子表格保存爲CSV,那麼使用任何腳本生成INSERT語句列表非常容易語言將按照與電子表格完全相同的順序執行。下面是在Groovy一個簡單的例子,但任何腳本語言會很容易地做到這一點,如果沒有更簡單:

def file1 = new File('c:\\temp\\yourSpreadsheet.csv') 
def file2 = new File('c:\\temp\\yourInsertScript.sql') 

def reader = new FileReader(file1) 
def writer = new FileWriter(file2) 

reader.transformLine(writer) { line -> 
    fields = line.split(',') 

    text = """INSERT INTO table1 (col1, col2, col3) VALUES ('${fields[0]}', '${fields[1]}', '${fields[2]}');""" 

} 

然後,您可以執行你的「yourInsertScript.sql」對您的數據庫和您的訂單將是相同的電子表格。

0

您還可能能夠在您的表中的數據加載過程中定義身份列自動遞增。這樣,您可以稍後再次對相同順序的記錄進行排序。

+3

訂單被插入時混入了。你的方法將無法工作 – 2008-10-10 19:17:42

1

經過大量研究,似乎很明顯,由於Microsoft提供了大量插入命令,所以無法保留行插入命令。您必須自己直接將ID列添加到導入文件中,使用shell或其他外部腳本,否則您不需要。它似乎是微軟需要添加的一個必需(而且很容易)的功能,但是經過十多年沒有任何進展,這種情況不會發生。

但是我需要在導入文件中保存實際的記錄順序,因爲如果設置的列具有相同的值,較高的記錄將取代較低的記錄。

所以我走了一條不同的路線。我的制約因素:

  • 我無法改變的源文件都沒有。 (並設置了一個不好的先例!)
  • 我無法使用外部腳本。太複雜。它必須是一個簡單的基於T-Sql的解決方案,不需要執行CMD。這需要進入一個單一的程序,以便它可以自動化。

我喜歡使用Powershell爲每行創建有序插入語句,然後在Sql中運行的邏輯。它基本上是將每個記錄排隊等待每個插入,而不是BULK插入。是的,它會工作,但它也會很慢。我經常擁有500K +行的文件。我需要快速的東西。

所以我整個XML跑。批量將文件直接上傳到單個XML變量中。這將保留記錄的順序,因爲每個記錄都添加到XML中。然後解析XML變量並將結果插入表中,同時添加標識列。

有一個假設,即導入文件是一個標準的文本文件,每個記錄在一個換行結束(CHAR(13)+ CHAR(10))

我的方法有兩個步驟:

  1. 執行IMPORT SQL語句(使用OPENROWSET),使用XML標記封裝每個記錄。將結果捕獲到一個XML變量中。

  2. 通過解析XML標記變量到一個表中,加入遞增[ID]列。

    --------------------------------- 
    Declare @X xml; 
    --------------------------------- 
    SELECT @X=Cast('<X>'+Replace([BulkColumn],Char(13)+Char(10),'</X><X>')+'</X>' as XML) 
    FROM OPENROWSET (BULK N'\\FileServer\ImportFolder\ImportFile_20170120.csv',SINGLE_CLOB) T 
    --------------------------------- 
    SELECT [Record].[X].query('.').value('.','varchar(max)') [Record] 
    ,ROW_NUMBER() OVER (ORDER BY (SELECT 100)) [ID] 
    --Into #TEMP 
    FROM @X.nodes('X') [Record](X); 
    --------------------------------- 
    
    • XML標記替換每個換行。

    • 如果文件以換行結束,這將導致在結尾添加一個空白行。只需刪除最後一行。

我使用動態SQL,所以我可以通過在文件名和將ID設置爲開始在1或0(如果有一個標題行)寫到我的過程這一點。

我能夠對抗的300K記錄的文件中約5秒鐘運行此。

相關問題