【问题标题】:Run-time error '3708': Parameter Object is improperly defined. Inconsistent or incomplete information was provided运行时错误“3708”:参数对象定义不正确。提供的信息不一致或不完整
【发布时间】:2015-12-01 07:32:05
【问题描述】:

我尝试使用 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
  1. 我有一个运行该过程的 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
    

    那是代码..我哪里错了

【问题讨论】:

  • 请尝试设置 cmd.ActiveConnection = Conn 而不是不设置并且您不需要指定 cmd.Parameters.Refresh
  • VBA 代码中的哪一行给出了错误?如果要使用 Parameters.Refresh,则不应附加参数。而是使用:Parameters.Item(@Name).Value = Value。 (在您可能已经尝试过的注释行中,您使用封装引号来设置值,这是不必要的。)我认为您的问题在于您的输出参数。不幸的是,我也不知道如何在 VBA 中正确设置它们。

标签: sql-server vba


【解决方案1】:

首先,由于您使用的是Parameters.Refresh,因此您不想将参数附加到参数集合中。相反,在将值应用于 输入 参数时,您应该使用以下格式:

cmd.Parameters.Item(Input_Variables(i).Name).Value = Input_Variables(i).Value

您在 VBA 代码中注释掉了这样一行。我认为这意味着您以前尝试过。但是,您使用单引号 (') 封装了您的 Input_Variables(i).Value。你不应该这样做。您只需要确保您传递的值与参数设置的类型相同。 (注意: 在您的情况下,您的所有 Input_Variables 都是字符串,因此您的 InsertProcedure 函数仅适用于只有字符串类型参数的存储过程。

这同样适用于您的 输出 参数。但是,您可能不需要或不想设置它们的值,除非您实际上将它们用作输入和输出参数。

您的输出参数之一是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 的任何值。)

  1. 使用Parameters.Refresh 自动设置命令的参数集合时,您可以手动覆盖任何VARCHAR(MAX) 输出参数大小的设置,使其小于2147483647:

    cmd.Parameters.Item(Output_Variables(i).Name).Size = 2147483646
    
  2. 或者,将存储过程的VARCHAR out 参数设置为小于 2147483647:

    @SP_Message VARCHAR(2147483646) = '' OUTPUT
    
  3. 或者,不要使用Parameters.Refresh,而是手动创建所有参数并将它们附加到命令的集合中。您的输出参数将附加如下内容:

    cmd.Parameters.Append cmd.CreateParameter(Output_Variables(i).Name, _
        adVarChar, _
        adParamInputOutput, _
        2147483646)
    

【讨论】:

  • 非常有用的答案。
猜你喜欢
  • 2016-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-12
  • 1970-01-01
  • 2020-09-10
  • 1970-01-01
相关资源
最近更新 更多