如果不指定可选参数,则无法调用存储过程

时间:2012-07-07 04:17:30

标签: sql sql-server stored-procedures ado.net

我正在尝试使用几个必需参数和几个可选参数调用存储过程。在我出现之前,程序的开头是这样编写的:

USE [MYDB]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[SP_GetStudents]
(
    @SortOrder          varchar(50),
    @SortColumn         varchar(150),
    @SortLetter         varchar(10),
    @Status             varchar(250),
    @PageIndex              int,
    @PageSize           int,
    @User_ID            int,
    @Reference_No           varchar(50) = NULL,
    @First_Name         varchar(50) = NULL,
    @Middle_Name            varchar(50) = NULL,
    @Last_Name          varchar(50) = NULL
)
As
BEGIN
-- other stuff here

一切似乎都很好。然后我在最后添加了另一个参数:

USE [MYDB]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[SP_GetStudents]
(
    @SortOrder          varchar(50),
    @SortColumn         varchar(150),
    @SortLetter         varchar(10),
    @Status             varchar(250),
    @PageIndex              int,
    @PageSize           int,
    @User_ID            int,
    @Reference_No           varchar(50) = NULL,
    @First_Name         varchar(50) = NULL,
    @Middle_Name            varchar(50) = NULL,
    @Last_Name          varchar(50) = NULL,
    @ContextID          int = NULL
)
As
BEGIN
-- other stuff here

现在它已经坏了。当我使用ADO.NET通过设置带参数的命令对象来调用存储过程时,它会抛出异常,因为我没有设置@ContextID参数。

知道为什么吗?我想如果我将它设置为默认值NULL,那么它实际上是完全可选的。

更新:这里是SqlCommand的设置方式,我最好能代表它:

SqlCommand cmd = new SqlCommand("SP_GetStudents");
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter param = new SqlParameter();
param.ParameterName = "@SortOrder";
param.Value = sortOrder;
param.Direction = ParameterDirection.Input;

SqlParameter param2 = new SqlParameter();
param2.ParameterName = "@SortColumn";
param2.Value = sortColumn;
param2.Direction = ParameterDirection.Input;
cmd.Parameters.Add(param);
cmd.Parameters.Add(param2);
cmd.Parameters.Add(new SqlParameter("@SortLetter", sortLetter));
cmd.Parameters.Add(new SqlParameter("@Status", status));
cmd.Parameters.Add(new SqlParameter("@PageIndex", pageIndex));
cmd.Parameters.Add(new SqlParameter("@PageSize", pageSize));

// here, the code splits a search expression into multiple parameters, looping over a switch statement like this:

foreach (string token in tokens)
{
    switch(token)
    {
        case "Reference_No":
            cmd.Parameters.Add(new SqlParameter("@Reference_No", (object)value ?? DBNull.Value));
            break;
        case "First_Name":
            cmd.Parameters.Add(new SqlParameter("@First_Name", (object)value ?? DBNull.Value));
            break;
        case "Last_Name":
            cmd.Parameters.Add(new SqlParameter("@Last_Name", (object)value ?? DBNull.Value));
            break;
        case "Middle_Name":
            cmd.Parameters.Add(new SqlParameter("@Middle_Name", (object)value ?? DBNull.Value));
            break;
        case "Generation":
            cmd.Parameters.Add(new SqlParameter("@Generation", (object)value ?? DBNull.Value));
            break;
        case "ContextID":
            cmd.Parameters.Add(new SqlParameter("@ContextID", (object)value ?? DBNull.Value));
            break;
    }
}

cmd.Parameters.AddWithValue("@User_ID", userID);
// fires off cmd through a DAL

这是例外(类型System.Data.SqlClient.SqlException):

  

参数化查询'(@ Reference_No varchar(50),                                         @First_Name varchar(5'需要参数'@ContextID',这是未提供的。

我发现此消息有点奇怪,因为格式化似乎已经失效。无论如何,在引擎盖下,命令通过SqlDataAdapter执行,该DataSet用于填充Fill。在{{1}}方法执行期间抛出异常。

1 个答案:

答案 0 :(得分:0)

在这个http://msdn.microsoft.com/en-us/library/ms187926.aspx链接上提到以下行..

  

除非定义参数的默认值或将值设置为等于另一个参数,否则在调用过程时,必须由用户提供每个声明的参数的值。如果过程包含表值参数,并且调用中缺少参数,则传入一个空表。

所以基于此我可以说,如果你把“默认”键工作,你的问题就会得到解决。

同样在同一页面上提到有关默认的信息,详情如下。

  

默认   参数的默认值。如果为参数定义了默认值,则可以在不指定该参数的值的情况下执行该过程。默认值必须是常量,或者可以为NULL。常量值可以采用通配符的形式,从而可以在将参数传递给过程时使用LIKE关键字。见下面的例C.

     

默认值仅记录在sys.parameters.default列中   用于CLR程序。对于Transact-SQL,该列将为NULL   程序参数。

谢谢, Jigar