我正在尝试在 Excel VBA 中使用 ADO 在 SQL Server 中填充单列临时表。我的代码非常慢,即 1,000 行需要 145 秒。
有没有更快的方法涉及不涉及操作原始 SQL 字符串的可维护的优雅代码?我喜欢 .AddNew 和 .UpdateBatch ... 如果做不到这一点,最快的方法是什么?
Private Sub StackOverflowPopTempTable(cn As ADODB.Connection)
Dim rs As ADODB.Recordset
Dim row As Long
Dim strSql As String
Dim row_count As Long
Dim t As Single
t = Timer
Set rs = New ADODB.Recordset
'Create a temporary table
strSql = "IF OBJECT_ID('tempdb..##tbl_dummy_data', 'U') IS NOT NULL " & _
"DROP TABLE ##tbl_dummy_data; " & _
"CREATE TABLE ##tbl_dummy_data ( " & _
"dummy_data VARCHAR(20) PRIMARY KEY " & _
");"
cn.Execute strSql
'Add masterkeys to this exclusion table
strSql = "SELECT * FROM ##tbl_dummy_data"
rs.Open strSql, cn, adOpenStatic, adLockBatchOptimistic
row_count = 1000
For row = 1 To row_count
rs.AddNew
rs("dummy_data") = "a" & row
Next row
Debug.Print Timer - t
rs.UpdateBatch
Set rs = Nothing
Debug.Print Timer - t
End Sub
UpdateBatch语句最多只需要半秒。剩下的 2 分钟左右是 UpdateBatch 语句。
非常感谢-我会同时更新我发现的任何东西......
更新一
这需要相同的时间
cn.BeginTrans
row_count = 1000
For row = 1 To row_count
strSql = "INSERT INTO ##tbl_dummy_data VALUES ('a" & row & "')"
cn.Execute strSql
Next row
Debug.Print Timer - t
cn.CommitTrans
Debug.Print Timer - t`
更新 2
IF OBJECT_ID('tempdb..##tbl_dummy_data', 'U') IS NOT NULL
DROP TABLE ##tbl_dummy_data;
CREATE TABLE ##tbl_dummy_data (
dummy_data VARCHAR(20) PRIMARY KEY
);
Insert Into ##tbl_dummy_data
Select Cast(rand(checksum(newid()))*1000000 as int);
go 1000
服务器端需要 2 分钟
更新三
这只需要几分之一秒,所以我怀疑 VBA 正在做单独的交易?即使我使用 .BeginTrans 和 .CommitTrans?
DECLARE @counter INT
SET @counter = 0
BEGIN TRANSACTION
WHILE @counter < 1000
BEGIN
Insert Into ##tbl_dummy_data
Select Cast(rand(checksum(newid()))*1000000 as int);
SET @counter = @counter + 1
END
COMMIT TRANSACTION
更新四
检查供应商是否支持交易。显然是这样!
?cn.Properties("Transaction DDL").Value
8
一个答案(尽管它是 v hacky)似乎是将所有 INSERT 放入一个字符串中。这需要 1 秒
Private Sub StackOverflowPopTempTableRaw(cn As ADODB.Connection)
Dim row As Long
Dim strSql As String
Dim row_count As Long
Dim t As Single
t = Timer
'Create a temporary table
strSql = "IF OBJECT_ID('tempdb..##tbl_dummy_data', 'U') IS NOT NULL " & _
"DROP TABLE ##tbl_dummy_data; " & _
"CREATE TABLE ##tbl_dummy_data ( " & _
"dummy_data VARCHAR(20) PRIMARY KEY " & _
");"
cn.Execute strSql
'Add masterkeys to this exclusion table
row_count = 1000
For row = 1 To row_count
strSql = strSql & "INSERT INTO ##tbl_dummy_data VALUES ('a" & row & "'); "
Next row
cn.Execute strSql
Debug.Print Timer - t
End Sub