使用 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 的 VBA 查询

将查询从 SQL Server 转换为 Access 2000

从 Excel VBA 更新 SQL Server 表

SQL Server 存储过程向其调用者报告进度,一个 Access (VBA DAO) 传递查询

使用 VBA 将 Excel 表连接到 SQL Server

从Excel vba中的SQL Server数据中检索/创建记录集