我尝试使用VBA代码从Access表单运行存储过程,但我一直收到错误(“运行时错误'3708':参数对象定义不正确。提供的信息不一致或不完整“)。有人可以帮我弄清楚我哪里错了。
。 1.我有一个名为“ CurrTbl ”的表和一个名为“ ManageCurrency ”的存储过程
CREATE TABLE [dbo].[CurrTbl](
[CurrencyID] [int] IDENTITY(1,1) NOT NULL,
[CurrencyCountry] [varchar](250) NOT NULL,
[CurrencyName] [varchar](250) NOT NULL,
[ISOCODE] [varchar](3) NOT NULL,
[lg_user] [varchar](150) NULL,
CONSTRAINT [PK_CurrencyName] PRIMARY KEY CLUSTERED
(
[CurrencyID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
ALTER TABLE [dbo].[CurrTbl] ADD CONSTRAINT [DF_CurrTbl_lg_user] DEFAULT (original_login()) FOR [lg_user]
GO
CREATE procedure [dbo].[ManageCurrency]
@CurCountry varchar(250),
@CurName varchar(250),
@ICode varchar(3),
@Flag smallint = 0 OUTPUT,
@SP_Message Varchar(MAX) = '' OUTPUT
AS
BEGIN
DECLARE @si AS BIGINT = 0;
If (ISNULL(@CurCountry,'') <> '' and ISNULL(@ICode,'') <> '')
BEGIN
merge dbo.CurrTbl as T
USING (Select @CurCountry AS CurrencyCountry, @CurName AS CurrencyName, @ICode as ISOCode) AS S
ON (T.CurrencyCountry = S.CurrencyCountry and T.ISOCode = S.ISOCode)
WHEN NOT MATCHED BY TARGET
THEN INSERT (CurrencyCountry,CurrencyName,ISOCode)
VALUES (@CurCountry,@CurName,@ICode)
WHEN MATCHED
THEN UPDATE SET T.CurrencyName = @CurName;
-- Getting the lastest scope identity of the last entry
SELECT @si = CurrencyID from dbo.CurrTbl where CurrencyID = SCOPE_IDENTITY();
END
If (ISNULL(@si,'')<> '') SET @SP_Message = 'Operation Sucessful'; Set @Flag = 1;
If (ISNULL(@si,'')= '') Set @SP_Message = 'Operation Not Sucessful'; Set @Flag = 0;
END
我有一个运行程序的VBA代码
Public Type SP_Variable
Name As String
Value As String
End Type
Private Sub Command0_Click()
Dim SQL_Var(3) As SP_Variable
Dim Out_Var(2) As SP_Variable
SQL_Var(1).Name = "@CurCountry"
SQL_Var(1).Value = "KAMPALA"
SQL_Var(2).Name = "@CurName"
SQL_Var(2).Value = "KAMPALA SHILLING"
SQL_Var(3).Name = "@ICode"
SQL_Var(3).Value = "KSH"
Out_Var(1).Name = "@Flag"
Out_Var(1).Value = ""
Out_Var(2).Name = "@SP_Message"
Out_Var(2).Value = ""
Call InsertProcedure("ManageCurrency", SQL_Var, 3, Out_Var, 2)
End Sub
Public Function InsertProcedure(ProcedureName As String, ByRef Input_Variables() As SP_Variable, InputVar As Integer, ByRef Output_Variables() As SP_Variable, OutputVar As Integer) As String
Dim Conn As ADODB.Connection
Dim cmd As ADODB.Command
Dim rs As ADODB.Recordset
Dim sConnect As String
sConnect = "driver={sql server};server=Svr;Database=Data_DB;UID=user;PWD=password;"
'' Establish connection.
Set Conn = New ADODB.Connection
Conn.ConnectionString = sConnect
Conn.Open
'' Open recordset.
Set cmd = New ADODB.Command
cmd.ActiveConnection = Conn
cmd.CommandText = ProcedureName
cmd.CommandType = adCmdStoredProc
cmd.CommandTimeout = 0
cmd.Parameters.Refresh
''For i = 1 To InputVar
''cmd.Parameters(SP_Variables(i).Name).Value = SP_Variables(i).Value
''cmd.Parameters.Append cmd.CreateParameter(Input_Variables(i).Name, adVarChar, adParamInput, 350)
''cmd.Parameters.Item(Input_Variables(i).Name).Value = "'" & Input_Variables(i).Value & "'"
cmd.Parameters.Append cmd.CreateParameter("@CurCountry", adVarChar, adParamInput, 250, Input_Variables(3).Value)
cmd.Parameters.Append cmd.CreateParameter("@CurName", adVarChar, adParamInput, 250, Input_Variables(3).Value)
cmd.Parameters.Append cmd.CreateParameter("@ICode", adVarChar, adParamInput, 3, Input_Variables(3).Value)
''Next i
''For i = 1 To OutputVar
'' ''cmd.Parameters(SP_Variables(i).Name).Value = SP_Variables(i).Value
'' cmd.Parameters.Append cmd.CreateParameter(Output_Variables(i).Name, adVarChar, adParamInputOutput, 2000, Output_Variables(i).Value)
'' Next i
Set rs = cmd.Execute
SP_Message = cmd.Parameters("@SP_Message").Value
SP_Flag = cmd.Parameters("@Flag").Value
' Process results from recordset, then close it.
rs.Close
Set rs = Nothing
End Function
那是代码..我哪里出错
答案 0 :(得分:0)
首先,由于您使用的是Parameters.Refresh
,因此您不希望将参数附加到参数集合中。相反,在将值应用于输入参数时,您应该使用以下格式:
cmd.Parameters.Item(Input_Variables(i).Name).Value = Input_Variables(i).Value
你的VBA代码中注释了这样的一行。我认为这意味着你以前尝试过。但是,您使用单引号(Input_Variables(i).Value
)封装了'
。你不应该这样做。您只需要确保传递的值与参数设置的类型相同。 (注意: 在您的情况下,所有Input_Variables
都是字符串,因此您的InsertProcedure
函数仅适用于只包含字符串类型参数的存储过程。< / em>的)
这同样适用于输出参数。但是,除非您实际将它们用作输入和输出参数,否则您可能不需要或不想设置它们的值。
您的一个输出参数属于VARCHAR(MAX)
类型。 Parameters.Refresh
调用很可能将该参数的Size
设置为2,147,483,647,这是VBA中Long
类型的最大正值。不幸的是,由于我承认我不完全理解的原因,您可以设置adVarChar
参数的实际最大大小比该值(2,147,483,646)小1。我最好的猜测是没有太多关注它是涉及某种开销。将尺寸保留为2,147,483,647将导致您收到的错误。
您有三个选项可以解决VBA中的VARCHAR(MAX)
ADO输出参数问题。 (对于下面的所有选项,我使用值2147483646,但它可以是任何大于0且小于2147483647的值。):
使用Parameters.Refresh
自动设置命令的参数集合时,您可以手动覆盖任何VARCHAR(MAX)
输出参数大小的设置,使其小于2147483647:
cmd.Parameters.Item(Output_Variables(i).Name).Size = 2147483646
或者,设置存储过程的VARCHAR
输出参数,其大小小于2147483647:
@SP_Message VARCHAR(2147483646) = '' OUTPUT
或者,不要使用Parameters.Refresh
而是手动创建所有参数并将它们附加到命令的集合中。您的输出参数将附加如下:
cmd.Parameters.Append cmd.CreateParameter(Output_Variables(i).Name, _
adVarChar, _
adParamInputOutput, _
2147483646)