Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 如何使用SqlBulkCopy保持行顺序?_Sql Server_Excel_Import_Export_Sqlbulkcopy - Fatal编程技术网

Sql server 如何使用SqlBulkCopy保持行顺序?

Sql server 如何使用SqlBulkCopy保持行顺序?,sql-server,excel,import,export,sqlbulkcopy,Sql Server,Excel,Import,Export,Sqlbulkcopy,我正在使用SqlBulkCopy以编程方式将数据从Excel导出到SQLServer2005。它工作得很好,我唯一的问题是它没有保留Excel文件中的行序列。我没有要排序的列,我只希望这些记录以它们在Excel电子表格中显示的相同顺序插入 我不能修改Excel文件,必须使用我所拥有的。按任何现有列进行排序都会中断序列 请帮忙 最后,在电子表格中插入ID列,看起来在导出/导入过程中无法保持顺序如果您可以将excel电子表格保存为CSV,则很容易使用任何脚本语言生成INSERT语句列表,这些语句将以

我正在使用SqlBulkCopy以编程方式将数据从Excel导出到SQLServer2005。它工作得很好,我唯一的问题是它没有保留Excel文件中的行序列。我没有要排序的列,我只希望这些记录以它们在Excel电子表格中显示的相同顺序插入

我不能修改Excel文件,必须使用我所拥有的。按任何现有列进行排序都会中断序列

请帮忙


最后,在电子表格中插入ID列,看起来在导出/导入过程中无法保持顺序

如果您可以将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”,您的顺序将与电子表格相同。

我认为sql不会指定或保证行顺序,除非您使用“order by”子句

来自比尔·沃恩()的帖子:

使用Order By:即使表已 聚集索引(用于存储 数据(按物理顺序排列),SQL Server 不保证行将被删除 以该方式返回(或任何特定) 订购,除非订购依据条款生效 用过

另一个信息链接:


您还可以在表中定义一个标识列,该列在数据加载期间自动递增。通过这种方式,您可以在以后希望记录再次按相同顺序排序时对其进行排序。

经过大量研究后,似乎很明显,使用批量插入命令无法保留行顺序,因为它是由Microsoft编写的。您要么自己直接将ID列添加到导入文件中,要么使用shell或其他外部脚本,要么不使用。这似乎是微软需要(而且很容易)添加的功能,但在他们十多年一无所获之后,这不会发生

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

所以我走了另一条路。我的限制是:

  • 我根本无法更改源文件。(并开创了一个糟糕的先例!)
  • 我无法使用外部脚本。太复杂了。它必须是一个简单的基于T-Sql的解决方案,没有CMD执行。这需要进入一个单一的过程,这样才能实现自动化
我喜欢使用Powershell为每行创建有序insert语句,然后在Sql中运行的逻辑。它本质上是将每条记录排队等待单个插入,而不是批量插入。是的,它会起作用,但也会很慢。我经常有超过500K行的文件。我需要快一点的东西

所以我遇到了XML。将文件直接大容量上载到单个XML变量中。这将保留每个记录添加到XML时的顺序。然后解析XML变量并将结果插入表中,同时添加标识列

假设导入文件是一个标准文本文件,每条记录以换行符结尾(Char(13)+Char(10))

我的方法有两个步骤:

  • 执行importsql语句(使用OPENROWSET),用XML标记封装每个记录。将结果捕获到XML变量中

  • 通过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);
    ---------------------------------
    
    ---------------------------------
    声明@xxml;
    ---------------------------------
    选择@X=Cast(“”+Replace([BulkColumn],Char(13)+Char(10),“”)+XML格式)
    从OPENROWSET(批量N'\\FileServer\ImportFolder\ImportFile\u 20170120.csv',单个\u CLOB)T
    ---------------------------------
    选择[Record].[X]。查询('.')。值('.','varchar(max)')[Record]
    ,第_行编号()超过(订购人(选择100))[ID]
    --进入#临时
    来自@X.nodes('X')[记录](X);
    ---------------------------------
    
    • XML标记替换每个换行符

    • 如果文件以换行结束,这将导致在末尾添加一个空行。只需删除最后一行

  • 我使用动态sql将其写入过程中,以便传入文件名并将ID设置为从1或0开始(如果有标题行)


    我能够在大约5秒钟内对一个包含300K条记录的文件运行此操作。

    鉴于SQL表本身就是无序的,您如何判断插入顺序是不同的?一个自动递增列?插入过程中顺序会混淆。你的方法行不通