3

我正在使用 SqlBulkCopy 以编程方式将数据从 Excel 导出到 SQL Server 2005。它很好用,我唯一的问题是它没有保留我在 Excel 文件中的行序列。我没有要排序的列,我只想按照它们在 Excel 电子表格中出现的顺序插入记录。

我无法修改 Excel 文件,必须使用我所拥有的。按任何现有列排序将破坏序列。

请帮忙。

PS 最终将 ID 列插入电子表格,看起来在导出/导入期间无法保持订单

4

4 回答 4

3

我不认为 SQL 指定或保证行排序,除非您使用“ORDER BY”子句。

来自 Bill Vaughn 的一篇文章(http://betav.com/blog/billva/2008/08/sql_server_indexing_tips_and_t.html):

使用 Order By:即使表具有聚集索引(以物理顺序存储数据),SQL Server 也不保证行将按该(或任何特定)顺序返回,除非使用 ORDER BY 子句。

另一个信息链接:

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

于 2008-10-10T00:44:24.227 回答
1

经过大量研究后,显然没有办法使用 Microsoft 提供的 Bulk Insert 命令来保留行顺序。您必须自己将 ID 列直接添加到导入文件中,使用 shell 或其他外部脚本,或者不这样做。微软似乎需要(而且很容易)添加一个功能,但是在他们十多年没有任何东西之后,它不会发生。

然而,我需要在导入后保留导入文件中的实际记录顺序,因为如果一组列具有相同的值,较高的记录将取代较低的记录。

于是我走了一条不同的路。我的限制是:

  • 我根本无法更改源文件。(并开创了一个不好的先例!)
  • 我无法使用外部脚本。太复杂。它必须是一个简单的基于 T-Sql 的解决方案,没有 CMD 执行。这需要进入一个单一的程序,以便它可以自动化。

我喜欢使用 Powershell 为每一行创建有序插入语句,然后在 Sql 中运行的逻辑。它本质上是将每条记录排队等待单独插入而不是批量插入。是的,它会起作用,但它也会很慢。我经常有包含 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 将其写入我的过程中,因此我可以传入 FileName 并将 ID 设置为从 1 或 0 开始(以防有标题行)。

我能够在大约 5 秒内针对 300K 记录的文件运行它。

于 2017-04-28T22:31:19.983 回答
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”,您的订单将与您的电子表格相同。

于 2008-10-10T00:41:15.980 回答
0

您还可以在表中定义一个在数据加载期间自动递增的标识列。这样,当您希望记录再次以相同顺序排列时,您可以对其进行排序。

于 2008-10-10T00:44:58.780 回答