从VBA中的数组大容量插入sql

从VBA中的数组大容量插入sql,sql,sql-server,vba,excel,Sql,Sql Server,Vba,Excel,我正在尝试在excel中构建一个按钮,将所选区域上载到sql server中的表中。第一行将自动视为列标题 这件事怎么办?我想要的是简单和超快速上传 这是我的主意--- 我将获取所选区域,然后将其保存为.txt文件,然后对其运行大容量insert语句。是否有一种方法可以直接批量插入所选区域(可能先将其放入变量数组中),而不首先将其保存为.txt文件 另外,如果有一种更有效的方法,那么一定要提出。我将从与服务器的简单ADO连接开始,执行一系列INSERT INTO语句,看看它的性能如何。如果这不起

我正在尝试在excel中构建一个按钮,将所选区域上载到sql server中的表中。第一行将自动视为列标题

这件事怎么办?我想要的是简单和超快速上传

这是我的主意---

我将获取所选区域,然后将其保存为.txt文件,然后对其运行大容量insert语句。是否有一种方法可以直接批量插入所选区域(可能先将其放入变量数组中),而不首先将其保存为.txt文件


另外,如果有一种更有效的方法,那么一定要提出。

我将从与服务器的简单ADO连接开始,执行一系列INSERT INTO语句,看看它的性能如何。如果这不起作用,那么可以考虑使用相同的INSERT INTO语句创建一个文本文件。那可能更快,我真的不知道。下面是一些将范围转换为所需SQL语句的代码

Function RangeToInsert(rRng As Range) As String

    Dim vaData As Variant
    Dim i As Long, j As Long
    Dim aReturn() As String
    Dim aCols() As String
    Dim aVals() As Variant

    Const sINSERT As String = "INSERT INTO MyTable "
    Const sVAL As String = " VALUES "

    'Read in data
    vaData = rRng.Value

    'Create arrays
    ReDim aReturn(1 To UBound(vaData))
    ReDim aCols(1 To UBound(vaData, 2))
    ReDim aVals(1 To UBound(vaData, 2))

    'Fill column name array from first row
    For j = LBound(vaData, 2) To UBound(vaData, 2)
        aCols(j) = vaData(1, j)
    Next j

    'Go through the rest of the rows
    For i = LBound(vaData, 1) + 1 To UBound(vaData, 1)

        'Fill a temporary array
        For j = LBound(vaData, 2) To UBound(vaData, 2)
            aVals(j) = vaData(i, j)
        Next j

        'Build the string into the main array
        aReturn(i) = sINSERT & "(" & Join(aCols, ",") & ")" & sVAL & "(" & Join(aVals, ",") & ");"
    Next i

    RangeToInsert = Join(aReturn, vbNewLine)

End Function
下面是我拼凑的一些虚假数据的输出:

?rangetoinsert(selection)

INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (97,100,53,27,14,53,94,43);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (21,96,69,60,70,8,35,54);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (8,12,78,38,82,67,41,53);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (15,32,89,100,61,78,16,37);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (46,37,75,66,66,93,19,45);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (82,30,56,10,99,2,1,29);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (98,39,98,96,95,60,16,73);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (65,79,69,70,74,86,15,59);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (30,37,12,57,86,94,6,53);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (1,20,91,65,20,26,96,57);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (81,7,68,65,56,27,81,80);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (94,42,43,33,46,82,44,24);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (88,48,34,83,58,64,36,90);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (51,28,43,70,12,29,96,27);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (62,54,76,86,92,41,40,84);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (11,21,32,30,65,6,22,75);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (44,72,38,73,44,93,4,16);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (39,90,96,16,9,6,17,50);
您可以将其放入ADO连接上的执行调用中,或将其写入文本文件。我无法想象还有什么比使用SQL语句更快的了。例如,您可以在循环可更新记录集时更新.Fields.Value属性,但没有比这更快的方法了


但是,如果要做一百万行,VBA中的任何东西都不会很快。所以请记住这一点。

我将从与服务器的一个简单ADO连接开始,执行一系列INSERT INTO语句,看看它的性能如何。如果这不起作用,那么可以考虑使用相同的INSERT INTO语句创建一个文本文件。那可能更快,我真的不知道。下面是一些将范围转换为所需SQL语句的代码

Function RangeToInsert(rRng As Range) As String

    Dim vaData As Variant
    Dim i As Long, j As Long
    Dim aReturn() As String
    Dim aCols() As String
    Dim aVals() As Variant

    Const sINSERT As String = "INSERT INTO MyTable "
    Const sVAL As String = " VALUES "

    'Read in data
    vaData = rRng.Value

    'Create arrays
    ReDim aReturn(1 To UBound(vaData))
    ReDim aCols(1 To UBound(vaData, 2))
    ReDim aVals(1 To UBound(vaData, 2))

    'Fill column name array from first row
    For j = LBound(vaData, 2) To UBound(vaData, 2)
        aCols(j) = vaData(1, j)
    Next j

    'Go through the rest of the rows
    For i = LBound(vaData, 1) + 1 To UBound(vaData, 1)

        'Fill a temporary array
        For j = LBound(vaData, 2) To UBound(vaData, 2)
            aVals(j) = vaData(i, j)
        Next j

        'Build the string into the main array
        aReturn(i) = sINSERT & "(" & Join(aCols, ",") & ")" & sVAL & "(" & Join(aVals, ",") & ");"
    Next i

    RangeToInsert = Join(aReturn, vbNewLine)

End Function
下面是我拼凑的一些虚假数据的输出:

?rangetoinsert(selection)

INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (97,100,53,27,14,53,94,43);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (21,96,69,60,70,8,35,54);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (8,12,78,38,82,67,41,53);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (15,32,89,100,61,78,16,37);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (46,37,75,66,66,93,19,45);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (82,30,56,10,99,2,1,29);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (98,39,98,96,95,60,16,73);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (65,79,69,70,74,86,15,59);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (30,37,12,57,86,94,6,53);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (1,20,91,65,20,26,96,57);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (81,7,68,65,56,27,81,80);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (94,42,43,33,46,82,44,24);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (88,48,34,83,58,64,36,90);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (51,28,43,70,12,29,96,27);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (62,54,76,86,92,41,40,84);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (11,21,32,30,65,6,22,75);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (44,72,38,73,44,93,4,16);
INSERT INTO MyTable (F1,F2,F3,F4,F5,F6,F7,F8) VALUES (39,90,96,16,9,6,17,50);
您可以将其放入ADO连接上的执行调用中,或将其写入文本文件。我无法想象还有什么比使用SQL语句更快的了。例如,您可以在循环可更新记录集时更新.Fields.Value属性,但没有比这更快的方法了


但是,如果要做一百万行,VBA中的任何东西都不会很快。所以请记住这一点。

首先您需要编写一个函数(我的函数名为insert form)

因此,如果我选择4列,其中2行包含

1 2 3 4
5 6 7 8
此函数创建('1','2','3','4'),('5','6','7','8')) 然后,我可以在INSERT SQL语句中使用它,如下所示:


插入到TableName值InsertForm(Range)

首先您需要编写一个函数(我的函数称为INSERT form)

因此,如果我选择4列,其中2行包含

1 2 3 4
5 6 7 8
此函数创建('1','2','3','4'),('5','6','7','8')) 然后,我可以在INSERT SQL语句中使用它,如下所示:


在TableName中插入值InsertForm(范围)

sql server
在问题中提到,但标记为
mysql
?表可能有多大?@whytheq本身没有一般限制。从10-10^7行。10^7…从Excel-如何?(Excel工作表中有1百万行可用)
sql server
在问题中提到,但标记为
mysql
?表可能有多大?@whytheq本身没有一般限制。从10-10^7行。10^7…从Excel-如何?(Excel工作表中有100万行可用)“如果你要做100万行,VBA中的任何东西都不会太快”虽然这通常是正确的(我自己也说过),但有一种方法可以解决这个问题:将数据转储到带分隔符的文本文件中,然后使用SQL Server BCP实用程序导入它。很糟糕,但这是从VBA加载100万行的唯一真正快速的方法。仅供参考:使用INSERT语句的文本文件方法不太可能比直接的VBA更快。@RBARYYOUNG bulk INSERT语句确实是最快的。我对此毫无疑问。问题在于将excel工作表转换为管道分隔的文本文件。我不知道这会有多快,因为我将不得不在每个单元格后附加一个管道,然后将其打印在txt文件中。这意味着一个强力双循环的顺序(行数)*(列数)。这就是为什么我在寻找一种从数组而不是txt文件大容量插入的方法。@DickKusleika在这种情况下,如果文本值需要用引号括起来,你会如何处理这些值?@DickKusleika Check,我也这么认为,但我希望会有一种更优雅的方法:)谢谢“如果你要做一百万行,VBA中没有什么东西是快的”,而这通常是正确的(我自己也说过),有一种方法可以解决这个问题:将数据转储到带分隔符的文本文件中,然后使用SQL Server BCP实用程序.Kludgy导入它,但这是从VBA加载100万行的唯一真正快速的方法。仅供参考:使用INSERT语句的文本文件方法不太可能比直接的VBA更快。@rbaryYoung批量INSERT语句是indeed是最快的。我对此毫不怀疑。问题在于将excel工作表转换为以管道分隔的文本文件。我不知道这会有多快,因为我必须在每个单元格后附加管道,然后将其打印到txt文件中。因此,这意味着一个强力双循环顺序(行数)*(列数)。这就是为什么我在寻找一种从数组而不是txt文件大容量插入的方法。@DickKusleika在这种情况下,如果文本值需要用引号括起来,您将如何处理文本值?@DickKusleika Check,我也这么认为,但我希望能有一种更优雅的方法:)谢谢