【问题标题】:How to return values from a SQL Server Stored Procedure and Utilise them in Access VBA如何从 SQL Server 存储过程返回值并在 Access VBA 中使用它们
【发布时间】:2012-09-06 14:34:52
【问题描述】:

我在 SQL Server 中设置了一个运行良好的存储过程。我现在可以从 VBA 调用它,但想返回一个值以了解是否有任何错误等。我的 SP 中的最后一个参数设置为 OUTPUT:

@DataSetID int = 0,
@Destination char(1)='-',
@errStatusOK bit OUTPUT

下面是我调用 SP 的 VBA,但现在无法正常工作,添加新参数后我不确定哪里出错了,我不断收到3708 - Parameter object is improperly defined. Inconsistent or incomplete information was provided.

Set cnn = New adodb.Connection
cnn.ConnectionString = 
   "DRIVER=SQL Server;SERVER=SERVER\SERVER;DATABASE=a_db;Trusted_Connection=Yes"

cnn.Open cnn.ConnectionString

Set cmd = New adodb.Command
cmd.ActiveConnection = cnn
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "stprMoveDataSet"

Set param = cmd.CreateParameter
               ("@DataSetID", adInteger, adParamInput, , stDataSet)
cmd.Parameters.Append param
Set param = cmd.CreateParameter
               ("@Destination", adChar, adParamInput, 1, stDestination)
cmd.Parameters.Append param
Set param = cmd.CreateParameter
               ("@errStatusOK", adBit, adParamReturnValue)
cmd.Parameters.Append param

rs.CursorType = adOpenStatic
rs.CursorLocation = adUseClient
rs.LockType = adLockOptimistic
rs.Open cmd

如何让 vba 与 OUTPUT 参数一起工作并使 vba 的返回值“可读”。

编辑 - 我已将问题更改为更具体地关于返回值,而不仅仅是关于使用 OUTPUT 参数。

【问题讨论】:

    标签: sql-server vba sql-server-2008 ms-access stored-procedures


    【解决方案1】:
    Set cnn = New adodb.Connection
    cnn.ConnectionString = 
       "DRIVER=SQL Server;SERVER=SERVER\SERVER;DATABASE=a_db;Trusted_Connection=Yes"
    
    cnn.Open cnn.ConnectionString
    
    Set cmd = New adodb.Command
    cmd.ActiveConnection = cnn
    cmd.CommandType = adCmdStoredProc
    cmd.CommandText = "stprMoveDataSet"
    
    Set param1 = cmd.CreateParameter
                   ("@DataSetID", adInteger, adParamInput, , stDataSet)
    cmd.Parameters.Append param
    Set param2 = cmd.CreateParameter
                   ("@Destination", adChar, adParamInput, 1, stDestination)
    cmd.Parameters.Append param
    Set param3 = cmd.CreateParameter
                   ("@errStatusOK", adBit, adParamOutput, , adParamReturnValue)
    cmd.Parameters.Append param
    
    rs.CursorType = adOpenStatic
    rs.CursorLocation = adUseClient
    rs.LockType = adLockOptimistic
    rs.Open cmd
    

    【讨论】:

    • 你一定是在我发布自己的答案时发布了这个,我明白我现在在 CreateParameter 上出了什么问题。非常感谢,以后可能会用到。
    【解决方案2】:

    使用 VBA 获取值的方法有多种。

    1. 唱片集
    2. 受影响的记录数(仅适用于插入/更新/删除,否则为 -1)
    3. 输出参数
    4. 返回值

    我的代码演示了所有四个。这是一个返回值的存储过程:

    Create PROCEDURE CheckExpedite
        @InputX  varchar(10),
        @InputY int,
        @HasExpedite int out
    AS
    BEGIN
        Select @HasExpedite = 9 from <Table>
        where Column2 = @InputX and Column3 = @InputY
    
        If @HasExpedite = 9
            Return 2
        Else
            Return 3
    End
    

    这是我在 Excel VBA 中使用的子程序。您需要参考 Microsoft ActiveX Data Objects 2.8 Library。

    Sub CheckValue()
    
        Dim InputX As String: InputX = "6000"
        Dim InputY As Integer: InputY = 2014
    
        'open connnection
        Dim ACon As New Connection
        'ACon.Open ("Provider=SQLOLEDB;Data Source=<SqlServer>;" & _
        '    "Initial Catalog=<Table>;Integrated Security=SSPI")
    
        'set command
        Dim ACmd As New Command
        Set ACmd.ActiveConnection = ACon
        ACmd.CommandText = "CheckExpedite"
        ACmd.CommandType = adCmdStoredProc
    
        'Return value must be first parameter else you'll get error from too many parameters
        'Procedure or function "Name" has too many arguments specified.
        ACmd.Parameters.Append ACmd.CreateParameter("ReturnValue", adInteger, adParamReturnValue)
        ACmd.Parameters.Append ACmd.CreateParameter("InputX", adVarChar, adParamInput, 10, InputX)
        ACmd.Parameters.Append ACmd.CreateParameter("InputY", adInteger, adParamInput, 6, InputY)
        ACmd.Parameters.Append ACmd.CreateParameter("HasExpedite", adInteger, adParamOutput)
    
        Dim RS As Recordset
        Dim RecordsAffected As Long
    
        'execute query that returns value
        Call ACmd.Execute(RecordsAffected:=RecordsAffected, Options:=adExecuteNoRecords)
    
        'execute query that returns recordset
        'Set RS = ACmd.Execute(RecordsAffected:=RecordsAffected)
    
        'get records affected, return value and output parameter
        Debug.Print "Records affected: " & RecordsAffected
        Debug.Print "Return value: " & ACmd.Parameters("ReturnValue")
        Debug.Print "Output param: " & ACmd.Parameters("HasExpedite")
    
        'use record set here
        '...
    
        'close
        If Not RS Is Nothing Then RS.Close
        ACon.Close
    
    End Sub
    

    【讨论】:

      【解决方案3】:

      我最初查看了 OUTPUT 参数,但找不到如何将它们返回到 Access(在 VBA 中)然后向用户提供反馈。一位同事建议在存储过程中使用 SELECT 并使用它。

      存储过程: 最后添加以下内容:

      SELECT @errStatusOK as errStatusOK, @countCurrent as countCurrent, @countHistorical as countHistorical
      

      VBA:

      Dim cnn As ADODB.Connection
      Dim cmd As New ADODB.Command, rs As New ADODB.Recordset, param As New ADODB.Parameter
      Dim fld As ADODB.Field
      Dim stMessage As String
      
      Set cnn = New ADODB.Connection
      cnn.ConnectionString = "DRIVER=SQL Server;SERVER=SERVER\SERVER;DATABASE=a_db;Trusted_Connection=Yes"
      
      cnn.Open cnn.ConnectionString
      
      Set cmd = New ADODB.Command
      cmd.ActiveConnection = cnn
      cmd.CommandType = adCmdStoredProc
      cmd.CommandText = "stprMoveDataSet"
      
      Set param = cmd.CreateParameter("@DataSetID", adInteger, adParamInput, , stDataSet)
      cmd.Parameters.Append param
      Set param = cmd.CreateParameter("@Destination", adChar, adParamInput, 1, stDestination)
      cmd.Parameters.Append param
      
      rs.CursorType = adOpenStatic
      rs.CursorLocation = adUseClient
      rs.LockType = adLockOptimistic
      'rs.Open cmd
      Set rs = cmd.Execute
      If rs!errstatusok = True Then
          stMessage = "Operation appears to have been successful, check the DataSets Listing..." & Chr(13) & "Also, the Server returned the following information: ["
      Else
          stMessage = "Operation appears to have failed, check the DataSets Listing..." & Chr(13) & "Also, the Server returned the following information: ["
      End If
      For Each fld In rs.Fields
          stMessage = stMessage & "| " & fld.Name & " / " & fld.Value & " |"
      Next fld
      stMessage = stMessage & "]"
      
      MsgBox stMessage
      

      这将返回以下内容: Operation appears to have failed, check the DataSets Listing... Also, the Server returned the following information: [| errStatusOK / False || countCurrent / 0 || countHistorical / 10 |]

      【讨论】:

      • 您当然可以使用输出参数以及返回值或受影响的记录。看我的回答。
      【解决方案4】:

      在获取“adParamInput”的其他参数枚举中,另一个是“adParamOutput”,它表示存储过程的输出参数,“adParamInputOutput”表示“双向”的参数,因为它是。在你的情况下,我相信“adParamOutput”是合适的。我希望这就是你要找的。

      【讨论】:

      • 不是我想要的,但很有用。一位同事建议我只通过 SELECT @errStatusOK 等提供输出并在 VBA 中对其进行操作,这很有效。谢谢
      猜你喜欢
      • 2014-03-31
      • 2012-09-06
      • 1970-01-01
      • 2020-12-11
      • 1970-01-01
      • 2010-11-23
      • 2023-04-01
      • 2015-10-06
      • 1970-01-01
      相关资源
      最近更新 更多