Sql server 形式参数"&引用@回应"&引用;未声明为输出参数,但实际参数传入请求的输出

Sql server 形式参数"&引用@回应"&引用;未声明为输出参数,但实际参数传入请求的输出,sql-server,vb.net,output,Sql Server,Vb.net,Output,是的,我看过这个问题。不,它没有解决我的问题 我正在用VB.Net开发一个与SQL Server数据库接口的应用程序。目前,我正在尝试让VB.Net应用程序在数据库上执行以下存储过程: CREATE PROCEDURE dbo.AddSupplierAddress( @Supplier VARCHAR(100), @Street VARCHAR(100), @City VARCHAR(50), @Region VARCHAR(50), @C

是的,我看过这个问题。不,它没有解决我的问题

我正在用VB.Net开发一个与SQL Server数据库接口的应用程序。目前,我正在尝试让VB.Net应用程序在数据库上执行以下存储过程:

CREATE PROCEDURE dbo.AddSupplierAddress(
    @Supplier VARCHAR(100),
    @Street   VARCHAR(100),
    @City     VARCHAR(50),
    @Region   VARCHAR(50),
    @Code     VARCHAR(7),
    @Info     VARCHAR(500) = NULL,
    @response NVARCHAR(500) = OUTPUT
) AS
BEGIN
    DECLARE @SupplierID INT, @RegionID INT
    SELECT @SupplierID = supplier_id
      FROM suppliers
     WHERE supplier_name = @Supplier
    IF @SupplierID IS NULL
    BEGIN
        SET @response = 'Could not add address to Supplier "' + @Supplier + '".  Supplier does not exist.'
        RETURN
    END
    SELECT @RegionID = region_id
      FROM regions
     WHERE region_name = @Region
    IF @RegionID IS NULL
    BEGIN
        SET @response = 'Could not add address to Supplier "' + @Supplier + '". Region "' + @Region + '" does not exist.'
        RETURN
    END
    IF(EXISTS(SELECT supplier_id, street FROM supplier_addresses WHERE supplier_id = @SupplierID AND street = @Street))
    BEGIN
        SET @response = 'Could not add address to Supplier "' + @Supplier + '".  Address already exists in database.'
        RETURN
    END
    BEGIN TRANSACTION AddSuppAddr
    BEGIN TRY
        INSERT supplier_addresses(supplier_id, street, city, region_id, zip_code, notes)
        VALUES (@SupplierID, @Street, @City, @RegionID, @Code, @Info)
        COMMIT TRANSACTION AddSuppAddr
        SET @response = 'Success'
    END TRY
    BEGIN CATCH
        ROLLBACK TRANSACTION AddSuppAddr
        DECLARE @varErrorMessage NVARCHAR(4000), @varErrorSeverity INT, @varErrorState INT;
        SELECT @varErrorMessage = ERROR_MESSAGE(), @varErrorSeverity = ERROR_SEVERITY(), @varErrorState = ERROR_STATE();
        RAISERROR(@varErrorMessage, @varErrorSeverity, @varErrorState);
    END CATCH
END
GO
现在,我使用以下方法在数据库本身上运行了此过程:

DECLARE @Resp NVARCHAR(500)
EXEC AddSupplierAddress 'Test Name', '123 main st.', 'Hamilton', 'Ontario', 'L84B5N', NULL, @Resp
PRINT @Resp
这个程序运行良好。(我遇到的一个小问题是,在数据库上测试这些过程时,
@Resp
从未设置为我的输出值,但这是另一个我不想在这里解决的问题)。在我的VB.Net程序中,我尝试使用以下代码运行此过程:

Private Sub CreateBtn_Click(sender As Object, e As EventArgs) Handles createBtn.Click
    If CreateSupplier(supplierTxt.Text, websiteTxt.Text, True) Then
        Dim message As String = ""
        If setAddress Then
            If AddSupplierAddress(supplierTxt.Text, streetTxt.Text, cityTxt.Text, regionTxt.Text, codeTxt.Text, infoTxt.Text, True) Then
                message = "Supplier and address have been added to the database."
            Else
                DeleteSupplier(supplierTxt.Text)
                Return
            End If
        Else
            message = "Supplier has been added to the database."
        End If
        If MessageBox.Show(message & vbCrLf & "Would you like to add any Contacts?", "Data Added", MessageBoxButtons.YesNo) = DialogResult.Yes Then
            Dim contact As New NewContactForm(supplierTxt.Text, False, True) With {
                .MdiParent = MdiParent
            }
            contact.Show()
        End If
    End If
End Sub

Public Function AddSupplierAddress(ByVal supplier As String,
                                   ByVal street As String,
                                   ByVal city As String,
                                   ByVal region As String,
                                   ByVal code As String,
                                   Optional info As String = "",
                                   Optional displayError As Boolean = False) As Boolean
    Dim errorMsg As String = ""
    Dim CMD As New SqlCommand("AddSupplierAddress")
    CMD.Parameters.Add("@Supplier", SqlDbType.VarChar).Value = supplier
    CMD.Parameters.Add("@Street", SqlDbType.VarChar).Value = street
    CMD.Parameters.Add("@City", SqlDbType.VarChar).Value = city
    CMD.Parameters.Add("@Region", SqlDbType.VarChar).Value = region
    CMD.Parameters.Add("@Code", SqlDbType.VarChar).Value = code
    If Not info.Equals("") Then CMD.Parameters.Add("@Info", SqlDbType.VarChar).Value = info
    If ExecuteCMDWithReturnValue(CMD, errorMsg) Then
        Return True
    Else
        If displayError Then
            MessageBox.Show(errorMsg, "Database Error")
            Return False
        Else
            Return False
        End If
    End If
End Function

Public Function ExecuteCMDWithReturnValue(ByRef CMD As SqlCommand, ByRef errorMessage As String) As Boolean
    Try
        OpenDBConnection()
        CMD.Parameters.Add("@response", SqlDbType.NVarChar, 500).Direction = ParameterDirection.Output
        CMD.Connection = DB_CONNECTION
        CMD.CommandType = CommandType.StoredProcedure
        CMD.ExecuteNonQuery()
        Dim result As String = CMD.Parameters("@response").Value
        If result.Equals("Success") Then
            ExecuteCMDWithReturnValue = True
        Else
            errorMessage = result
            ExecuteCMDWithReturnValue = False
        End If
    Catch ex As Exception
        Throw New Exception("Database Error: " & ex.Message)
        ExecuteCMDWithReturnValue = False
    Finally
        CloseDBConnection()
    End Try
End Function
正如我上面所说的,当我在数据库上运行存储过程时,我没有得到这个错误。更奇怪的是,我还有另一套编码完全相同的程序,唯一的区别是,
supplier
的每个实例都被
customer
替换,它们都工作得很好

我得到的具体错误在标题中,但您不必向上滚动其:

未将形式参数“@response”声明为输出参数,而是在请求的输出中传递的实际参数


是什么导致了我的问题?

恭喜你,你遇到了一个糟糕的T-SQL问题。它“允许”字符串参数默认值不带引号地指定,以便

@response NVARCHAR(500) = OUTPUT
实际上相当于

@response NVARCHAR(500) = 'OUTPUT'
这当然与将参数声明为输出参数不同,因为这是

@response NVARCHAR(500) OUTPUT
这一点尤其糟糕,因为默认值只允许常量,而不允许函数或表达式,但引号是可选的,这会导致一些真正误导性的声明:

@from DATETIME = GETDATE

只有在调用过程时,如果没有为
@from
指定值,此操作才会失败:此时字符串
'GETDATE'
将转换为
DATETIME
(当然会失败)。

恭喜,您遇到了一个糟糕的T-SQL问题。它“允许”字符串参数默认值不带引号地指定,以便

@response NVARCHAR(500) = OUTPUT
实际上相当于

@response NVARCHAR(500) = 'OUTPUT'
这当然与将参数声明为输出参数不同,因为这是

@response NVARCHAR(500) OUTPUT
这一点尤其糟糕,因为默认值只允许常量,而不允许函数或表达式,但引号是可选的,这会导致一些真正误导性的声明:

@from DATETIME = GETDATE

只有在调用过程时,如果没有为
@from
指定值,此操作才会失败:此时字符串
'GETDATE'
将转换为
DATETIME
(当然,这会失败)。

@response-NVARCHAR(500)=OUTPUT
是一种合法声明,如果未传入,将为
@response
提供
'OUTPUT'
的默认值,因为T-SQL允许在此处使用不带引号的字符串,例如。。。原因。但是您想要的是
@response NVARCHAR(500)输出
…。那
=
是如何达到目的的/你觉得这样不好吗?尝试将
@from DATETIME=GETDATE
放在那里,认为如果没有提供参数,它会给您一个合理的默认值。(提示:不会。)@Jeroenmoster:这难道不是一个答案而不是一个评论吗?@Meta Knight:我想,虽然我不知道这是否有用,是否会被未来的读者再次发现…
@response NVARCHAR(500)=OUTPUT
是一种合法声明,如果未传入,将为
@response
提供
'OUTPUT'
的默认值,因为T-SQL允许在此处使用不带引号的字符串,例如。。。原因。但是您想要的是
@response NVARCHAR(500)输出
…。那
=
是如何达到目的的/你觉得这样不好吗?尝试将
@from DATETIME=GETDATE
放在那里,认为如果没有提供参数,它会给您一个合理的默认值。(提示:不会。)@Jeroenmoster:这难道不是一个答案而不是一个评论吗?@Meta Knight:我想,尽管我不知道这是否会有用,是否会被未来的读者再次发现……希望这个答案能对未来的其他人有所帮助。至少,有相同错误的人可能会了解恼人的T-SQL问题……希望这个答案对将来的其他人有所帮助。至少,有相同错误的人可能会了解恼人的T-SQL问题。。。。