我的 vba 代码被设计为 return 使用输出参数的存储过程(在 SQL 中)的值,但我无法获得 return 的值
My vba code is designed return a value from a stored procedure (in SQL) using an output parameter, but I am unable to get a value to return
我在 return 将 SQL table 中的值转换为 vba 中的变量时遇到问题。我将动态 SQL 与一个存储过程一起使用,该存储过程接受 4 个输入参数和一个输出参数。执行存储过程后,应将 return 作为参数传入的金属类型的密度。我目前 运行 使用硬编码测试值作为参数的代码,因此我可以期待输出。我认为问题不在于我的连接或我传递参数的方式 - 但无论如何我都会展示它们。
每当我设置我的变量 'output'(字符串),等于存储过程的输出参数时,我得到错误 0。
如果我的代码中缺少某些内容,请告诉我。否则,如果有更好的方法 returning 输出参数,我也可以尝试。
我尝试使用设置值在 SQL 中执行存储过程。
当我通过在 SSMS 中右键单击它来执行存储过程时,下面的代码是自动生成的(我想看看它是如何从 vba 执行的)- 因为它是 returning错误的值 我认为问题出在我的存储过程中,不一定 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
此查询的输出 return@record_value 参数等于 0.163,这是正确的,但参数 @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 中查找 return 数据库中的单个值,请不要使用记录集。 (虽然我想你可以)原因是 Recordsets 被设计为 return 形式的 table 数据 - 这给我带来了很多问题。
要return一个单一的值,你所要做的就是在vba中执行你的SQL命令,然后将你的return变量设置为等于您存储过程的输出参数。如果这没有意义,我将所有工作代码放在下面 vba 和我的存储过程。
TEST SUB - 我用它来测试来自 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
我在 return 将 SQL table 中的值转换为 vba 中的变量时遇到问题。我将动态 SQL 与一个存储过程一起使用,该存储过程接受 4 个输入参数和一个输出参数。执行存储过程后,应将 return 作为参数传入的金属类型的密度。我目前 运行 使用硬编码测试值作为参数的代码,因此我可以期待输出。我认为问题不在于我的连接或我传递参数的方式 - 但无论如何我都会展示它们。
每当我设置我的变量 'output'(字符串),等于存储过程的输出参数时,我得到错误 0。
如果我的代码中缺少某些内容,请告诉我。否则,如果有更好的方法 returning 输出参数,我也可以尝试。
我尝试使用设置值在 SQL 中执行存储过程。
当我通过在 SSMS 中右键单击它来执行存储过程时,下面的代码是自动生成的(我想看看它是如何从 vba 执行的)- 因为它是 returning错误的值 我认为问题出在我的存储过程中,不一定 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
此查询的输出 return@record_value 参数等于 0.163,这是正确的,但参数 @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 中查找 return 数据库中的单个值,请不要使用记录集。 (虽然我想你可以)原因是 Recordsets 被设计为 return 形式的 table 数据 - 这给我带来了很多问题。
要return一个单一的值,你所要做的就是在vba中执行你的SQL命令,然后将你的return变量设置为等于您存储过程的输出参数。如果这没有意义,我将所有工作代码放在下面 vba 和我的存储过程。
TEST SUB - 我用它来测试来自 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