什么是从SQL Server更新工作表的最快方法

我的分析师每个星期都有一个发票表格,他们需要用支票号码和支票date来更新。 检查表存在于SQL服务器中。

我已经写了一个遍历电子表格的每一行的macros,用这样的语句打开一个ADOlogging集:

SELECT CheckNumber, CheckDate FROM CHECKS WHERE Invoice_Number = " & cells (i,2) 

…然后使用logging集中的字段将数字和date写入Excel电子表格中该行的前两列。

代码执行几百行是可以接受的,但是在有成千上万行的时候会很慢。

有更快的方式来更新Excel电子表格比使用ADO逐行查找吗? 例如,有没有办法在电子表格和SQL Server中的表之间进行SQL连接?

编辑:为了回应Jeeped的问题,这里有一些澄清。

我真正想要做的是find一种方法,用SQL Server中的信息“批量”更新Excel电子表格,而不是执行SQL查找,并将结果一次写入一行。 有没有办法做一个连接的等价物,并返回整个结果集在一个单一的logging集?

上面的发票例子确实代表了我每天遇到的一类问题。 最终用户有一个电子表格,其中包含他们的工作数据(如发票),他们希望我从SQL服务器表中添加信息。 例如,“使用列C中的发票号码,在列A中添加该发票的支票号码,在列B中添加检查date”。 另一个示例可能是“对于列b中的每个发票,将采购订单号添加到列a”。

Excel源列可以是数字或文本。 SQL表中的“匹配”列将是相应的数据types,即varchar或integer。 数据被正确地归一化,索引等等。更新通常会影响几百或者几千行,但是有时候会有多达二万到三万。

如果我可以find批处理行的方式,我可能会把它变成一个Excel加载项来简化这个过程。 出于这个原因,我想留在VBA中,因为我的高级用户可以扩展或修改它以满足他们的需求 – 我宁愿不用.NET语言编写它,因为那样我们需要专门给开发人员时间来修改和部署它。 Excel应用程序的安全性不在意,因为用户已经可以通过MS Access数据库中的ODBC链接表访问数据,并且我们已经在SQL Server上采取了适当的安全防范措施。

将stream程移至SSIS将需要实际业务stream程中不存在的可重复性。

在过去,我已经成功地将SQL服务器中的所有数据提取到客户端断开连接的ADOlogging集中。 然后,我遍历整个logging集创build一个VBA字典,将ID值(本例中为InvoiceNum)作为关键字,将logging集书签作为对项目。 然后循环使用“存在”function检查发票号码与字典的每个值。 如果find匹配项,则可以将logging集设置为书签,然后从logging集更新电子表格中的值。 假设发票表不是几百万行,这个方法应该certificate是快速的。

编辑:添加批处理尝试限制从大型数据集返回的logging。 (未经testing的代码示例)

 Public Sub UpdateInvoiceData(invoiceNumRng As Range) 'References: Microsoft ActiveX Data Objects xx 'References: Microsoft Scripting Runtime Dim cell As Range Dim tempCells As Collection Dim sqlRS As ADODB.Recordset Dim dict As Scripting.Dictionary Dim iCell As Range Dim testInvoiceNum As String Dim inClause As String Dim i As Long i = 1 For Each cell In invoiceNumRng If i Mod 25 = 0 Or i = invoiceNumRng.cells.Count Then 'break up loop into batches of 25:: Modify batch size here, try to find an optimal size. inClause = CreateInClause(tempCells) 'limit sql query with our test values Set sqlRS = GetInvoiceRS(inClause) 'retrieve batch results Set dict = CreateInvoiceDict(sqlRS) 'create our lookup dictionary For Each iCell In tempCells testInvoiceNum = iCell.Value 'get the invoice number to test If dict.Exists(testInvoiceNum) Then 'test for match sqlRS.Bookmark = dict.Item(testInvoiceNum) 'move our recordset pointer to the correct item iCell.Offset(0, 1).Value = sqlRS.Fields("CheckNum").Value iCell.Offset(0, 2).Value = sqlRS.Fields("CheckDate").Value End If Next iCell 'prepare for next batch of cells Set tempCells = Nothing Set tempCells = New Collection Else tempCells.Add cell End If i = i + 1 'our counter to determine batch size Next cell End Sub Private Function CreateInClause(cells As Collection) As String Dim retStr As String Dim tempCell As Range retStr = "" For Each tempCell In cells retStr = retStr & "'" & tempCell.Value & "'" & ", " 'assumes textual value, omit single quotes if numeric/int Next tempCell If Len(retStr) > 0 Then CreateInClause = Left(retStr, Len(retStr) - 2) 'trim off last comma value Else CreateInClause = "" 'no items End If End Function Private Function GetInvoiceRS(inClause As String) As ADODB.Recordset 'returns the listing of InvoiceData from SQL Dim cn As ADODB.Connection Dim rs As ADODB.Recordset Dim sql As String Set cn = New ADODB.Connection cn.ConnectionString = "Your Connection String" sql = "SELECT * FROM [Invoices] WHERE InvoiceID IN(" & incluase & ")" cn.Open rs.CursorLocation = adUseClient 'use clientside cursor since we will want to loop in memory rs.CursorType = adOpenDynamic rs.Open sql, cn Set rs.ActiveConnection = Nothing 'disconnect from connection here cn.Close Set GetInvoiceRS = rs End Function Private Function CreateInvoiceDict(dataRS As ADODB.Recordset) As Dictionary Dim dict As Scripting.Dictionary Set dict = New Scripting.Dictionary If dataRS.BOF And dataRS.EOF Then 'no data to process Else dataRS.MoveFirst 'make sure we are on first item in recordset End If Do While Not dataRS.EOF dict.Add CStr(dataRS.Fields("InvoiceNum").Value), dataRS.Bookmark dataRS.MoveNext Loop Set CreateInvoiceDict = dict End Function 

这样做的最好方法是使用SSIS并将信息(通过SSIS)插入到电子表格的范围中。 请记住,SSIS预计目标范围是空的,并且目标范围之上的一行也应该是空的。 如果你这样做,你可以通过Windows调度程序来安排SSIS作业。