我在使用VBA循环SQL查询时遇到问题,需要很长时间才能运行。 总循环次数是15分钟内的115次。有什么办法可以缩短查询时间吗? 这是我的代码:
Dim Conn As New ADODB.Connection
Dim mrs As New ADODB.Recordset
x = 1
DBPath = ThisWorkbook.FullName
sconnect = "Provider=SQLOLEDB;SERVER=DWSQL\BCAPP;Database=TEST;Uid=admin;Pwd=admin;"
Conn.Open sconnect
Do
If Sheets("Foil (+)").Cells(12, 12) <> "" And Sheets("Data").Cells(x, 3).Value Like "E*" Then
sSqlSting = "SELECT *FROM [TEST].[dbo].[process_details] where pos_no = '" & Sheets("Data").Cells(x, 3) & "' and scan_type = 'Anode Foil' and status = 'OK' and returned = 'N'"
Else
Sheets("Data").Cells(x, 3).Value = "E" & Sheets("Data").Cells(x, 3).Value
sSqlSting = "SELECT *FROM [TEST].[dbo].[process_details] where pos_no = '" & Sheets("Data").Cells(x, 3) & "' and scan_type = 'Anode Foil' and status = 'OK' and returned = 'N'"
End If
mrs.Open sSqlSting, Conn, adOpenForwardOnly
If Sheets("Data").Cells(1, 18) = "" Then
Sheets("Data").Cells(1, 18).CopyFromRecordset mrs
Else
Sheets("Data").Cells(Rows.Count, 18).End(xlUp).Offset(1, 0).CopyFromRecordset mrs
End If
mrs.Close
x = x + 1
Loop Until Sheets("Data").Cells(x, 3) = ""
Conn.Close
答案 0 :(得分:0)
sSqlSting = "SELECT *FROM [TEST].[dbo].[process_details] where scan_type = 'Anode Foil' and status = 'OK' and returned = 'N' and pos_no = in ('"
enter code here
Do
If Sheets("Foil (+)").Cells(12, 12) <> "" And Sheets("Data").Cells(x, 3).Value Like "E*" Then
sSqlSting = sSqlString & Sheets("Data").Cells(x, 3) & "','"
Else
Sheets("Data").Cells(x, 3).Value = "E" & Sheets("Data").Cells(x, 3).Value
sSqlSting = sSqlString & '" & Sheets("Data").Cells(x, 3) & "','"
End If
x = x + 1
Loop Until Sheets("Data").Cells(x, 3) = ""
sSqlSting = left(sSqlSting,len(sSqlsting)-1) & ")"
mrs.Open sSqlSting, Conn, adOpenForwardOnly
If Sheets("Data").Cells(1, 18) = "" Then
Sheets("Data").Cells(1, 18).CopyFromRecordset mrs
Else
Sheets("Data").Cells(Rows.Count, 18).End(xlUp).Offset(1, 0).CopyFromRecordset mrs
End If
mrs.Close
答案 1 :(得分:0)
一些想法......
由于您的代码有效,并且您可以做很多事情来加快工作表中的数据实际处理(115次迭代什么都没有),我的猜测是花费大量时间与数据库进行通信
就此而言,115次循环的15分钟非同寻常。
如果您还没有,请确保您有索引:
scan_type, status, returned, pos_no
我建议将这一切作为单个索引。
这是一个创可贴。你正在对同一张桌子进行115次扫描,这只会使每次扫描更有效率 - 就像115次去杂货店购买115件物品而开车而不是走路一样。
参数化您的查询。不是传递文字,而是设置一个参数并在每个循环中发送它。
这也是一个创可贴,并且更多地与礼仪有关而不是表现,尽管会有性能影响,因为你正在编写一次声明并执行115次而不是编译和执行115次。
更好的是,对表进行一次扫描。执行一次查询,将结果存储在数据结构中(Dictionary对象可能做得很好),然后循环并应用这些结果。
如果结果如下:
scan_type = 'Anode Foil' and status = 'OK' and returned = 'N'
是否足够小(<5000左右的记录),我只是预先运行并将其存储在字典中,然后遍历电子表格。
如果它真的很大,那么首先扫描电子表格,仅针对这115个项目运行查询,然后再次遍历电子表格以分配值。传入一个列表作为参数可能是不可能的(顺便说一下,它在PostgreSQL中),所以你的动态SQL方法可能就足够了。
如果到达列表中有数千个项目的点,最好的方法是将这些项目加载到临时表中,然后对表格进行连接。