使用 VBA 从 SQL Server 查询 VIEW
Posted
技术标签:
【中文标题】使用 VBA 从 SQL Server 查询 VIEW【英文标题】:Using VBA to query a VIEW from SQL Server 【发布时间】:2018-04-23 21:18:12 【问题描述】:我正在尝试创建一个 VBA 脚本,该脚本将从 RecordSet.Source
属性的视图 (SELECT * FROM view_name
) 中提取结果,但是在尝试时,我的 CloseConnection 错误处理程序不断被捕获。我可以使用像SELECT * FROM tbl_name
这样的简单查询从表中获取结果,没有任何问题。
下面是我正在使用的代码。注意:我的 Const 变量已删除 Provider 和 Database 信息。
我想这真的归结为是否有可能像从表中一样从视图中获取结果?
Option Explicit
Const ConStrMSSQL As String = _
"Provider=provider_name;Database=database_name;Trusted_Connection=yes;"
Sub test()
Dim formConnect As ADODB.connection
Dim formData As ADODB.recordSet
Dim formField As ADODB.Field
Set formConnect = New ADODB.connection
Set formData = New ADODB.recordSet
formConnect.ConnectionString = ConStrMSSQL
formConnect.Open
On Error GoTo CloseConnection
With formData
.ActiveConnection = formConnect
.Source = "SELECT * FROM v_data_extract_658"
.LockType = adLockReadOnly
.CursorType = adOpenForwardOnly
.Open
End With
On Error GoTo CloseRecordset
Sheets("test").Range("A1").Select
For Each formField In formData.Fields
ActiveCell.Value = formField.Name
ActiveCell.Offset(0, 1).Select
Next formField
Sheets("test").Range("A2").CopyFromRecordset formData
On Error GoTo 0
CloseRecordset:
formData.Close
CloseConnection:
formConnect.Close
End Sub
这是错误信息:
运行时错误 2147467259 (80004005):从 SQL Server 收到未知令牌
【问题讨论】:
在所有条件相同的情况下,查询视图应该看起来与查询表完全一样。注释掉错误处理程序:你得到的错误信息是什么? 我强烈建议您摆脱那些 ON ERROR GOTO。您需要了解错误。你所拥有的是一种我称之为 try/squelch 的反模式。优雅地处理错误并告诉用户发生了什么事。仅仅关闭窗口是一种“处理”错误的可怕方式。当程序刚刚关闭时,作为用户非常令人沮丧。 @SeanLange 你说得很好。请注意,这些错误处理程序不是最终产品;更多只是占位符。 是的,这应该可以正常工作。但请确保您有权访问视图中引用的所有对象。例如,视图可能会引用您无权访问的链接服务器资源。例如,我已经看到 DEV 中的查询构建在 STAGE/TEST 中的对象之上。 @TimWilliams 这是错误消息:运行时错误 2147467259 (80004005):从 SQL Server 收到未知令牌 【参考方案1】:我认为这里最大的问题是您还没有定义命令对象。
我有点“徒手”地把它放在一起,当然,没有测试它,但它应该能让你到达你需要去的地方。
Sub test()
On Error GoTo ErrorHandle:
Dim formConnect As ADODB.Connection
Set formConnect = New ADODB.Connection
formConnect.ConnectionString = ConStrMSSQL
Dim cmd As ADODB.Command
Set cmd = New ADODB.Command
formConnect.Open
With cmd
.ActiveConnection = formConnect
.CommandType = adCmdText
.CommandText = "SELECT * FROM v_data_extract_658"
.CommandTimeout = 30
End With
Dim formData As ADODB.Recordset
Set formData = New ADODB.Recordset
formData.Open cmd, , adOpenStatic, adLockReadOnly
Sheets("test").Range("A1").Select
Dim formField As ADODB.Field
For Each formField In formData.Fields
ActiveCell.value = formField.Name
ActiveCell.Offset(0, 1).Select
Next formField
Range("A2").CopyFromRecordset formData
On Error GoTo 0
Cleanup:
If Not formData Is Nothing Then
If formData.State <> adStateClosed Then formData.Close
Set formData = Nothing
End If
If Not formConnect Is Nothing Then
If formConnect.State <> adStateClosed Then formConnect.Close
Set formConnect = Nothing
End If
Set cmd = Nothing
Exit Sub
ErrorHandle:
MsgBox Err.Description
'Do whatever else is needed to respond to errors.
Resume Cleanup
End Sub
【讨论】:
只是提醒一下,我必须将 'formConnect.Open' 移到 'formConnect.ConnectionString = ConStrMSSQL' 下才能开始连接。我确实在这一行收到了一个错误:'formData.Open cmd, , adOpenStatic, adLockReadOnly' 错误消息:从 sql server 收到未知令牌 thx - 我已经更新了我的答案以反映您所做的更改。我想此时我会明确说明您希望检索的一些列,因为列名或列的内容可能会导致悲伤。 确认一下,您是说在 CommandText 属性中执行此操作并完全替换我现在拥有的内容吗? 对于这个“SELECT * FROM v_data_extract_658”,明确指定几列。选择一两个您希望保持一致的,例如主键列,或具有外键约束的列。目的是尝试并专门隔离阻塞点所在的位置。如果您可以返回至少几列(或仅一列),那么您将更好地了解在哪里寻找问题。 您使用的是哪个 ActiveX 库?我最近使用以下内容为多个用户部署了一个解决方案:Microsoft ActiveX Objects 2.7 库 - 接下来我会看看我是否在其他库中取得了更好的成功。我的解决方案返回 SQL 视图,并启动存储过程。【参考方案2】:使用 Excel 和 VBA 从 SLQ Server 获取 dta 非常容易(并非总是如此,但如今)。
Sub ADOExcelSQLServer()
' Carl SQL Server Connection
'
' FOR THIS CODE TO WORK
' In VBE you need to go Tools References and check Microsoft Active X Data Objects 2.x library
'
Dim Cn As ADODB.Connection
Dim Server_Name As String
Dim Database_Name As String
Dim User_ID As String
Dim Password As String
Dim SQLStr As String
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
Server_Name = "EXCEL-PC\SQLEXPRESS" ' Enter your server name here
Database_Name = "NORTHWND" ' Enter your database name here
User_ID = "" ' enter your user ID here
Password = "" ' Enter your password here
SQLStr = "SELECT * FROM [Customers]" ' Enter your SQL here
Set Cn = New ADODB.Connection
Cn.Open "Driver=SQL Server;Server=" & Server_Name & ";Database=" & Database_Name & _
";Uid=" & User_ID & ";Pwd=" & Password & ";"
rs.Open SQLStr, Cn, adOpenStatic
' Dump to spreadsheet
For iCols = 0 To rs.Fields.Count - 1
Worksheets("Sheet1").Cells(1, iCols + 1).Value = rs.Fields(iCols).Name
Next
With Worksheets("sheet1").Range("a2:z500") ' Enter your sheet name and range here
'.ClearContents
.CopyFromRecordset rs
End With
' Tidy up
rs.Close
Set rs = Nothing
Cn.Close
Set Cn = Nothing
End Sub
顺便说一句,您也可以试试这个(请更改以适合您的特定设置/配置)...
Sub Working2()
Dim con As Connection
Dim rst As Recordset
Dim strConn As String
Set con = New Connection
strConn = "EXCEL-PC\SQLEXPRESS;Database=Northwind;Trusted_Connection=True"
con.Open strConn
'Put a country name in Cell E1
Set rst = con.Execute("Exec dbo.MyOrders '" & ActiveSheet.Range("E1").Text & "'" & ActiveSheet.Range("E2").Text & "'")
'The total count of records is returned to Cell A5
ActiveSheet.Range("A5").CopyFromRecordset rst
rst.Close
con.Close
End Sub
更多详情请查看以下链接。
https://www.excel-sql-server.com/excel-sql-server-import-export-using-vba.htm#Excel%20Data%20Export%20to%20SQL%20Server%20Test%20Code
【讨论】:
我尝试了您提供的第一个选项,并通过错误处理收到了错误消息:“[Microsoft][ODBC Server Driver]Query timeout expired”在这行代码中:'rs.Open SQLStr, Cn , adOpenStatic'。我不确定这是否是原因,但 SQLStr 设置为从视图中提取数据。以上是关于使用 VBA 从 SQL Server 查询 VIEW的主要内容,如果未能解决你的问题,请参考以下文章
将查询从 SQL Server 转换为 Access 2000
SQL Server 存储过程向其调用者报告进度,一个 Access (VBA DAO) 传递查询