sql - 我的 vba 代码设计为使用输出参数从存储过程(在 SQL 中)返回一个值,但我无法获得要返回的值

标签 sql excel vba stored-procedures ssms

我无法将 SQL 表中的值返回到 vba 中的变量中。我将动态 SQL 与一个存储过程一起使用,该存储过程接受 4 个输入参数和一个输出参数。执行存储过程后应返回作为参数传入的金属类型的密度。我目前正在使用硬编码的测试值作为参数运行代码,所以我可以期待输出。我不认为问题出在我的连接或我传递参数的方式上 - 但无论如何我都会展示它们。

每当我将变量“输出”(字符串)设置为存储过程的输出参数时,我都会得到 ERROR 0。

如果我的代码中缺少某些内容,请告诉我。否则,如果有更好的返回输出参数的方法,我也可以尝试。

我尝试使用设置值在 SQL 中执行存储过程。

下面的代码是在我通过在 SSMS 中右键单击它来执行存储过程时自动生成的(我想看看它是如何从 vba 执行的)——因为它返回了错误的值 我认为问题出在我的存储过程中,不一定是 vba。

USE [AFCD]
GO

DECLARE @return_value int,
        @record_value nvarchar(max)

EXEC    @return_value = [dbo].[GET_ADDITIVE_DATA]
        @user_index = N'Titanium(1)',
        @primary_col_index = N'DENSITY',
        @secondary_col_index = N'WIRE_TYPE',
        @data_table_name = N'WIRE_INDEX',
        @record_value = @record_value OUTPUT

SELECT  @record_value as N'@record_value'

SELECT  'Return Value' = @return_value

GO

此查询的输出返回等于 0.163 的 @record_value 参数,这是正确的,但参数 @return_value 为 0,我不明白。

--存储过程:
USE AFCD
GO

ALTER PROCEDURE dbo.GET_ADDITIVE_DATA (@user_index nvarchar(max),
                                       @primary_col_index nvarchar(max),
                                       @secondary_col_index nvarchar(max), 
                                       @data_table_name nvarchar(max),
                                       @record_value nvarchar(max) output
                                       ) AS
BEGIN

    DECLARE @query nvarchar(max)

    SET @query = 'SELECT @record_value = ' + @primary_col_index  + 
             ' FROM ' + @data_table_name +
                 ' WHERE ' + @secondary_col_index + ' = ''' + @user_index + ''''

    EXEC sp_executesql @query, 
                   N'@record_value nvarchar(max) output', 
                   @record_value = @record_value output
END

' VBA 代码:
Private output As String
'-------------------------------------------------------------------------

' Parameters are passed in that will be used to create a SQL statement
' for a stored procedure.

Public Sub SQL_StoredProcedure(ByVal sql_ui As String, ByVal sql_pci As String, ByVal sql_sci As String, ByVal sql_dtn As String)

'
'
'
'
sqlcmd.ActiveConnection = sqlconxn ' makes the sql connection
    sqlcmd.CommandType = adCmdStoredProc ' sets command to a stored procedure
    sqlcmd.CommandText = "GET_ADDITIVE_DATA" ' name of the stored procedure

    ' Parameters that need to be called and defined whenever the stored procedure is called
    sqlcmd.Parameters.Append sqlcmd.CreateParameter("@user_index", adVarChar, adParamInput, 255)
    sqlcmd.Parameters.Append sqlcmd.CreateParameter("@primary_col_index", adVarChar, adParamInput, 255)
    sqlcmd.Parameters.Append sqlcmd.CreateParameter("@secondary_col_index", adVarChar, adParamInput, 255)
    sqlcmd.Parameters.Append sqlcmd.CreateParameter("@data_table_name", adVarChar, adParamInput, 255)
    sqlcmd.Parameters.Append sqlcmd.CreateParameter("@record_value", adVarChar, adParamOutput, 255)

    ' Parameter values are set equal to the values passed in through excel by the user
    ' The stored procedure in SQL opertaes using dynamic SQL so all inputs are defined as String values
    sqlcmd.Parameters("@user_index").Value = sql_ui
    sqlcmd.Parameters("@primary_col_index").Value = sql_pci
    sqlcmd.Parameters("@secondary_col_index").Value = sql_sci
    sqlcmd.Parameters("@data_table_name").Value = sql_dtn

    Set sqlrs = New ADODB.recordSet ' new recordset
    sqlrs.CursorType = adOpenStatic
    sqlrs.LockType = adLockOptimistic
    sqlrs.Open sqlcmd ' Execute the stored procedure

    output = sqlcmd.Parameters("@record_value").Value
    Debug.Print "OUTPUT: " & output

    sqlconxn.Close

End Sub

调试日志应该只显示密度值:

例子:

0.163

最佳答案

我想到了。对于任何想从 vba 的 SQL 中的数据库返回单个值时感到好奇的人,不要使用记录集。 (虽然我猜你可以)原因是 Recordsets 旨在以表格的形式返回数据 - 这给我带来了很多问题。

要返回单个值,您只需在 vba 中执行 SQL 命令,然后将返回变量设置为等于存储过程的输出参数的值。如果这没有意义,我已经将我所有的工作代码从 vba 和我的存储过程放在下面。

测试子 - 我用它来测试一个可能来自 excel 的输入示例。

Private Sub TestSub()

SQL_StoredProcedure "Stainless Steel", "DENSITY", "WIRE_TYPE", "WIRE_INDEX"

End Sub

VBA模块
Option Explicit

Private output As String

' Parameters are passed in that will be used to create a SQL statement
' for a stored procedure.
Public Sub SQL_StoredProcedure(ByVal sql_ui As String, _
                                ByVal sql_pci As String, _
                                ByVal sql_sci As String, _
                                ByVal sql_dtn As String)

    On Error GoTo RunTimeError

    Dim sqlconxn As ADODB.connection ' Connection between vba and SQL
    Dim sqlcmd As ADODB.Command ' Operates as a command between SQL and vba
    Dim sqlfld As ADODB.field ' Used to refer to the records or fields in SQL

    Dim output As String ' The output retrieved from the SQL stored procedure
    Dim conxnString As String ' Connection string is used to make the connection between vba and SSMS

    Application.ScreenUpdating = False

    ' String used to establish a connection to the database
    conxnString = '{your connection string}'

    ' Every time the SQL_StoredProcedure function is called a new instance of the
    ' connection, command, and recordset are made and then immediately closed once the function finishes
    Set sqlconxn = New ADODB.connection
    Set sqlcmd = New ADODB.Command

    sqlconxn.ConnectionTimeout = 30
    sqlconxn.Open conxnString ' makes the connection between SQL

    MsgBox "Connection 1 state: " & GetState(sqlconxn.state) ' Checks the status of the connection

    sqlcmd.CommandType = adCmdStoredProc ' sets command to a stored procedure
    sqlcmd.CommandText = "GET_ADDITIVE_DATA" ' name of the stored procedure
    sqlcmd.ActiveConnection = sqlconxn ' makes the sql connection

    ' Parameters that need to be called and defined whenever the stored procedure is called
    sqlcmd.Parameters.Append _
        sqlcmd.CreateParameter("@user_index", adVarChar, adParamInput, 255, sql_ui)
    sqlcmd.Parameters.Append _
        sqlcmd.CreateParameter("@primary_col_index", adVarChar, adParamInput, 255, sql_pci)
    sqlcmd.Parameters.Append _
        sqlcmd.CreateParameter("@secondary_col_index", adVarChar, adParamInput, 255, sql_sci)
    sqlcmd.Parameters.Append _
        sqlcmd.CreateParameter("@data_table_name", adVarChar, adParamInput, 255, sql_dtn)
    sqlcmd.Parameters.Append _
        sqlcmd.CreateParameter("@record_value", adVarChar, adParamOutput, 255)

    ' Executes the sql command with all parameters already passed in
    sqlcmd.Execute

    ' output string is set equal to the output parameter of the stored procedure
    output = sqlcmd.Parameters("@record_value").Value

    Debug.Print "OUTPUT: " & output ' prints whatever was returned from the SP

    sqlconxn.Close ' Closes the sqlconxn

    Exit Sub

RunTimeError: ' Reportd any errors that might occur in the system and

    Dim strError As String
    strError = "ERROR: " & Err.Number & vbCrLf & Err.Description
    MsgBox strError
    Debug.Print strError

Exit Sub

End Sub

检查状态功能 - 这只是连接确认
Private Function GetState(state As Integer) As String

    Select Case state
        Case adStateClosed
            GetState = "Closed"
        Case adStateOpen
            GetState = "Open"

    End Select

End Function

SQL 存储过程
USE AFCD
GO

ALTER PROCEDURE dbo.GET_ADDITIVE_DATA (@user_index nvarchar(max),
                                       @primary_col_index nvarchar(max),
                                       @secondary_col_index nvarchar(max), 
                                       @data_table_name nvarchar(max),
                                       @record_value nvarchar(max) output
                                       ) AS
BEGIN

    DECLARE @output_value nvarchar(max)
    DECLARE @query nvarchar(max)

    SET @query = 'SELECT @record_value = ' + @primary_col_index  + 
                 ' FROM ' + @data_table_name +
                 ' WHERE ' + @secondary_col_index + ' = ''' + @user_index + ''''

    EXEC sp_executesql @query, 
                       N'@record_value nvarchar(max) output', 
                       @record_value = @record_value output

END

输出
OUTPUT: 0.284

关于sql - 我的 vba 代码设计为使用输出参数从存储过程(在 SQL 中)返回一个值,但我无法获得要返回的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56693762/

相关文章:

java - 通过存储过程的多个结果集输出进行查询以获取列的值

c# - Gembox 电子表格 : Is it possible to apply "Convert To Number" for the cells with warning?

Excel 工作簿通过 vba 代码关闭,但仍在任务管理器的进程中运行

mysql - SQL 查询有问题

mysql - 当有多个 JOINS 时,使用非规范化设计不是更好吗?

sql - 在 MySQL 中存储图像

vba - 用于向表添加新行和数据的函数或子函数

python - 获取按索引定向的嵌套字典中的键和值列表

vba - 静默 VBA MSHTML HTMLDocument.CreateDocumentFromURL

excel - 通过自动过滤器删除需要太长时间