【问题标题】:VBA New Database ConnectionVBA 新建数据库连接
【发布时间】:2013-08-21 06:08:13
【问题描述】:

如何更改下面的代码以防止您在屏幕截图中看到。

我正在使用以下代码运行宏

Dim conn As ADODB.Connection
Dim rec1 As ADODB.Recordset
Dim thisSql As String

Set conn = New ADODB.Connection

Dim sConn As String
  sConn = "Provider=SQLOLEDB;Trusted_Connection=Yes;Server=xyz;Database=xyz;UID=xyz;PWD=xyz"
conn.Open sConn

' this is creating multiple connections.
Set rec1 = New ADODB.Recordset
rec1.Open thisSql, conn

运行 SQL Server 查询(大约 20 行长,包含 4 个连接)。一切都很好,除了在运行几次后我的数据库管理员说我的查询加载了太多数据库。

现在,我的查询可能会导致问题,也可能是 Excel 开始同时运行多个连接。这方面的一些证据是下面的屏幕截图以及数据库上的负载似乎随时间增加的事实。

如何在不不断创建新连接的情况下建立数据库连接?

有人在使用 Excel 数据库宏时遇到过类似问题吗?


更新

虽然下面的答案非常有用(尤其是对于刚开始使用 VBA 的人),但我的查询占用负载的主要原因似乎是多个连接的组合并且忽略了我的代码中的一行:

    With Sheets("FVols").QueryTables.Add(Connection:=rec1, Destination:=Sheets("FVols").Range("A1"))
    .name = "data"
    .FieldNames = True
    .Refresh BackgroundQuery:=True <<<<<<<<<<<<<<<<<<<<<<<-----

End With

【问题讨论】:

  • 没有看到更多的宏代码很难回答,但似乎你永远不会关闭连接,所以,是的,每次你的宏运行时,你都会创建一个新的连接。
  • @Tony,我最后写了 conn.Close,但它仍然创建了新的连接(rec1.Close 使宏崩溃)。还有什么我需要关闭的吗?

标签: sql excel adodb vba


【解决方案1】:

您只需要打开一次连接。这实际上意味着您可以在一个活动连接上执行多个查询。您必须关闭连接并释放引用(特别是使用 ADODB)以避免遇到冲突和其他与连接相关的问题。

如果您知道要执行的查询,您可以创建一个数组(或集合)并将查询添加到队列中。

虽然您已经有一个开放的连接可以使用,但您可以继续执行查询。

扫描代码,你的和我的没有太大区别,所以你应该能够看到发生了什么以及在哪里。如果有什么不清楚的地方,请在 cmets 中提问

   Sub DbConnection()

    Dim cn As ADODB.Connection
    Set cn = New ADODB.Connection
    Dim rs As ADODB.Recordset

    Dim strConn As String
    strConn = "Driver={SQL Server};Server=; Database=; UID=; PWD="

    cn.Open strConn

    Dim queryArr, i
    queryArr = Array("SELECT * FROM [MyTable]", "SELECT * FROM [MyOtherTable]")

    For i = LBound(queryArr) To UBound(queryArr)
        ExecuteQuery queryArr(i), cn, rs
    Next i

    cn.Close
    Set cn = Nothing
End Sub

Private Sub ExecuteQuery(query As Variant, ByRef cn As ADODB.Connection, ByRef rs As ADODB.Recordset)
    Set rs = New ADODB.Recordset
    With rs
        .ActiveConnection = cn
        .Open CStr(query)
        Sheets(1).Range("A1").CopyFromRecordset rs
        .Close
    End With
    Set rs = Nothing
End Sub

现在,您只需执行一次DBConnection(),您在数组中列出的所有查询都会被执行。

或者,如果您的查询是在运行时创建的,您可以将其作为参数传递给DbConnection()

Sub DbConnection(queryQueue As Collection)

    Dim cn As ADODB.Connection
    Set cn = New ADODB.Connection
    Dim rs As ADODB.Recordset


    Dim strConn As String
    strConn = "Driver={SQL Server};Server=HELIUM\PRI; Database=sourcedata; UID=tabula; PWD=Tabula123!"

    cn.Open strConn

    For i = 1 To queryQueue.Count
        ExecuteQuery queryQueue.Item(i), cn, rs
    Next i

    cn.Close
    Set cn = Nothing
End Sub

Private Sub ExecuteQuery(query As Variant, ByRef cn As ADODB.Connection, ByRef rs As ADODB.Recordset)
    Set rs = New ADODB.Recordset
    With rs
        .ActiveConnection = cn
        .Open CStr(query)
        Sheets(1).Range("A1").CopyFromRecordset rs
        .Close
    End With
    Set rs = Nothing
End Sub

更新:

您可以将您的连接声明为全局变量。现在您可以根据需要多次运行DBConnection(),而且您不会每次都创建新连接。相反,您将使用全局连接对象。

Option Explicit

Public cn As ADODB.Connection

Sub DbConnection()

    Set cn = New ADODB.Connection
    Dim rs As ADODB.Recordset

    Dim strConn As String
    strConn = "Driver={SQL Server};Server=; Database=; UID=; PWD="

    cn.Open strConn

    Set rs = New ADODB.Recordset
    With rs
        .ActiveConnection = cn
        .Open "SELECT * FROM [MyTable]"
        Sheets(1).Range("A1").CopyFromRecordset rs
        .Close
    End With
    Set rs = Nothing

    cn.Close
    Set cn = Nothing
End Sub

【讨论】:

  • 我只有一个查询,每次运行宏时我只需要运行一次。如果我使用您的方法,我不需要在每次运行宏时都运行 DbConnection - 这会创建一个新连接吗?谢谢
  • @frickskit 好的,我现在明白了。我已经更新了我的答案,看看
【解决方案2】:

您是否在完成后释放连接变量?即

Set rec1 = Nothing

否则连接不会完全关闭。

【讨论】:

  • 我刚刚将这个(和 Set conn = Nothing)添加到代码中。我仍然在我截取屏幕截图的窗口中获得了新的连接。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-05
  • 2021-02-09
  • 2011-02-02
  • 1970-01-01
  • 2017-11-14
相关资源
最近更新 更多