2013-08-19 37 views
3

如何更改下面的代碼以防止在屏幕截圖中看到的內容。VBA新建數據庫連接

我運行一個宏用下面的代碼

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數據庫宏的類似問題?

Multiple connections


UPDATE

雖然下面的答案是非常有用的(尤其是有人在VBA開始了),看來我的查詢被佔用的主要原因負載爲多個連接的組合,並忽略了我的代碼中的一行:

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

End With 
+2

沒有看到更多的宏代碼很難回答,但它似乎永遠不會關閉連接,所以,每次運行宏時都會創建一個新的連接。 – Tony

+0

@Tony,我寫了conn.Close結尾,但它仍然創建新的連接(rec1.Close崩潰宏)。還有什麼我需要關閉? – frickskit

回答

7

您只需要打開一次連接。這實際上意味着您可以在該活動連接上執行多個查詢。您必須關閉連接並釋放參考(專門用ADODB)以避免碰到碰撞和其他連接相關問題。

如果您知道要執行的查詢,可以創建一個數組(或集合),並向隊列中添加查詢。

雖然你已經有了一個開放的連接與你一起工作,你可以繼續執行查詢。

通過代碼掃描,你和我之間沒有太大的區別,所以你應該能夠看到發生了什麼和在哪裏。請,請在評論的問題,如果有不清楚的地方現在

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 
+0

我只有一個查詢,每次運行宏時我只需要運行一次。如果我使用你的方法,我不需要每次運行宏時都運行DbConnection - 這會創建一個新的連接?謝謝 – frickskit

+0

@frickskit好的我現在明白了。我已經更新了我的答案,看看 – 2013-08-19 13:11:18

0

是y當你完成它時釋放連接變量?即

Set rec1 = Nothing 

如果不是,連接將不會完全關閉。

+0

我剛剛添加了這個(並且設置conn = Nothing)代碼。我仍然在窗口中獲得了新的連接,但我截取了截圖。 – frickskit