スクリーンショットに表示されないように、以下のコードを変更する方法。
次のコードでマクロを実行しています
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
これはSQLServerクエリを実行します(長さは約20行で、4つの結合が含まれています)。数回実行した後、DB管理者が、クエリがDBをロードしすぎていると言っていることを除いて、すべて問題ありません。
今、私のクエリが問題を引き起こしている可能性があります、またはExcelが一度に複数の接続を実行し始めている可能性があります。これを示すいくつかの証拠は、以下のスクリーンショットと、データベースの負荷が時間とともに増加しているように見えるという事実です。
常に新しい接続を作成せずにDB接続を確立するにはどうすればよいですか?
Excel DBマクロの操作で同様の問題が発生した人はいますか?
[〜#〜] update [〜#〜]
以下の回答は非常に役立ちましたが(特にVBAを始めた人にとって)、クエリが負荷をかけている主な理由は、複数の接続の組み合わせとコードの行を見落としていたためと思われます。
With Sheets("FVols").QueryTables.Add(Connection:=rec1, Destination:=Sheets("FVols").Range("A1"))
.name = "data"
.FieldNames = True
.Refresh BackgroundQuery:=True <<<<<<<<<<<<<<<<<<<<<<<-----
End With
接続を開く必要があるのは1回だけです。これは文字通り、その1つのアクティブな接続で複数のクエリを実行できることを意味します。衝突やその他の接続関連の問題が発生しないように、接続を閉じて参照を解放する必要があります(特に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()
を1回実行するだけで、配列にリストしたすべてのクエリが実行されます。
または、クエリが実行時に作成される場合は、パラメータとして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
_
終了したら接続変数を解放しますか?つまり.
Set rec1 = Nothing
そうしないと、接続は完全に閉じません。