我的最终目标是针对 sql-server 运行 sql 查询并在电子表格中捕获返回的数据。以下代码大致反映了我当前的设置并且可以正常工作。该设计允许我从文本文件中读取 sql 代码并将其提交到 sql-server。“Sub ExecuteCRUD”提交第一个 sql 脚本以准备数据并将结果转储到临时表中。“Function loadRecordset”提交一个相对简单的选择查询并将返回的数据捕获到一个记录集中,然后我用它来填充一个电子表格。
我的设置中有几个“变量”可能与讨论相关。
我的 4 套 Sql 代码
ConnectionString(我的 vba 代码的一部分)
我其余的 vba 代码
一个。Dbo.ConnectionString = "Provider=MSDASQL;DRIVER=SQL Server;SERVER= myserver ;UID= id ;PWD=密码;DATABASE=数据库;"
湾。Dbo.ConnectionString = "Provider=SQLOLEDB;Data Source= myserver ;Initial Catalog= database ;User ID= id ;Password= password ;"
最初,我改变的只是连接字符串。直接结果是连接字符串版本 a 完美运行。使用 b 版本,我的设置将失败,而 sql-server 没有任何错误。
使用连接字符串版本 b,“Sub ExecuteCRUD”(数据准备步骤)仍然可以顺利运行。作为我的第一个 sql 脚本的结果,我可以验证临时表是在 tempdb 中创建的。
“Function loadRecordset”将通过行运行而不会出现任何错误,直至并包括“rs.open”。(我检查了错误,没有任何来自 ado 连接的错误)。
只有后面的代码,在使用记录集拷贝数据时会报错:“对象关闭时不允许操作”。
通过一些测试,我将问题范围缩小到 sql 代码。
我必须在这里重申。使用 ODBC 提供程序时,我的初始 sql 代码集运行良好。事情只是使用 OLEDB 提供程序进行。
使用 OLEDB 提供程序,“有问题的”sql 代码是Use databaseABC。此外,使用 ado,我的设置将 4 组 sql 代码提交到 sql server。第一组 sql 代码准备数据(创建表、插入数据、创建索引、使用 while 循环填充数据、使用递归 ctes 等)。在这第一组sql代码中,还包含了Use databaseABC ,它会成功执行。提交的另外 3 组 sql 代码只是以获取数据为目的的 select 查询。当使用databaseabc中包含使用databaseabc时,该操作的操作失败而没有任何错误。在我取出Use databaseABC之后,一切都将在 OLEDB 提供者世界中正常运行。
使用databaseABC不是选择查询的必要部分。使用它可以省去在连接子句中一直指定数据库名称的麻烦。
在这一点上,我的好奇心是双重的
- 为什么使用databaseABC会导致失败,特别是仅在使用 OLEDB 提供程序时,更具体地说,仅在运行选择查询时。
- 发生故障时,sql-server 或驱动程序是否应该产生任何错误?检查和验证的正确方法是什么?
Private Dbo As New ADODB.Connection
Private rs As ADODB.Recordset
Public Sub ConnectServer()
If Dbo.State = adStateClosed Then
Dbo.ConnectionString = "Provider=SQLOLEDB;Data Source=*server*;" _
& "Initial Catalog=*database*;User ID=*id*;Password=*pwd*;"
Dbo.Open
End If
End Sub
Public Sub ExecuteCRUD(ByVal Sql As String)
On Error GoTo PANIC
Dbo.Execute Sql
Exit Sub
PANIC:
Debug.Print Err.Descript
Stop
End Sub
Public Function loadRecordset(ByVal Sql As String) As Long
On Error GoTo PANIC
Set rs = New ADODB.Recordset
With rs
.CursorLocation = adUseClient
.CursorType = adOpenStatic
.LockType = adLockReadOnly
.Source = Sql
Set .ActiveConnection = Dbo
End With
rs.Open
loadRecordset = rs.RecordCount
Exit Function
PANIC:
Debug.Print Err.Description
loadRecordset = 0
Stop
End Function