MS-SQL存储过程不适用于空参数

时间:2015-01-13 17:44:25

标签: c# sql-server

我的表单中有输入' name'和#'电话'。

当它们有值时,一切正常:使用存储过程将记录插入到数据库中,spFoo:

String sp = "spFoo 'test name','test phone'";
OdbcCommand command = new OdbcCommand(sp, connection);
command.CommandType = System.Data.CommandType.StoredProcedure;
connection.Open();
Response.Write(command.ExecuteNonQuery().ToString());
  • 适用于申请
  • 适用于Mgmt Studio

但是当他们没有值时,我会在应用程序中得到-1作为回应:

String sp = "spFoo '',''";
  • 在应用程序(-1)
  • 中不起作用
  • 适用于Mgmt Studio

我希望用户能够在没有任何输入的情况下创建记录。

为什么这在管理工作室中有效,而在应用程序上无效?

更新:我在存储过程的参数中添加了默认值,它没有工作;我给了空字符串" NULL"作为代码中的值,仍然没有运气。这是服务器设置还是不允许空变量的东西?

4 个答案:

答案 0 :(得分:2)

您需要从存储过程中删除SET NOCOUNT ON;

来自documentation

  

停止显示受Transact-SQL语句或存储过程影响的行数计数的消息作为结果集的一部分返回。

正如其他人指出的那样,您也应该对查询进行参数化,但-1是由NOCOUNT ON引起的。

修改

我意识到这不是你要求的,但是要使用参数化查询和ODBC,你需要根据文档here使用?作为序数占位符。例如:

using (OdbcConnection connection = new OdbcConnection(connectionString))
{
    string sp = "{call spFoo (?, ?)}";

    using (OdbcCommand command = new OdbcCommand(sp, connection))
    {
        command.CommandType = System.Data.CommandType.StoredProcedure;

        connection.Open();
        //the order here is important, the names are not!
        command.Parameters.Add("@name", OdbcType.VarChar).Value = "test name";
        command.Parameters.Add("@phone", OdbcType.VarChar).Value = "test phone";

        Console.WriteLine(command.ExecuteNonQuery().ToString());
    }
}

答案 1 :(得分:0)

从代码调用存储过程时,应使用命令中的Parameters属性。试试这个:

String sp = "spFoo";
command.Parameters.Add("@name", "test name");
command.Parameters.Add("@phone", "test phone");

答案 2 :(得分:0)

正如JimmyV所说,你应该使用command.Parameters.Add方法来设置你的参数,每当没有指定参数值时传入null。为了解决有关错误'过程或函数'的注释,spFoo'期望参数'@name'(未提供'),您还需要修改存储过程以在未提供参数时使用默认值(例如null ):

CREATE PROCEDURE MyStoredProcedure
    @foo int = null
AS
BEGIN
...
END

很抱歉没有在上述帖子中添加评论。信誉不足!

答案 3 :(得分:0)

您不应该以当前的方式调用存储过程。你应该使用参数。您的代码易受SQL注入的影响。

永远不会对连续用户输入的值进行字符串化。

您应该拥有的是类似的存储过程设置:

CREATE PROCEDURE spFoo
    @name varchar(50) = 'Jim', -- default
    @phone varchar(50) = null -- optional
AS
BEGIN
    SET NOCOUNT ON;

    -- INSERT STATEMENT

END
GO

然后在代码中提供参数:

string name = this.nameTextBox.Text;
string phone = this.phoneTextBox.Text;

if (string.IsNullOrWhiteSpace(name))
    name = null;
if (string.IsNullOrWhiteSpace(phone))
    phone = null;

SqlConnection connection = new SqlConnection(@"<connection string>");

using (SqlCommand command = connection.CreateCommand())
{
    command.CommandType = CommandType.StoredProcedure;

    // leave this as the stored procedure name only
    command.CommandText = "spFoo";

    // if name is null, then Jim gets passed (see stored procedure definition)
    // if phone is null, then null gets passed (see stored procedure definition)
    command.Parameters.AddWithValue("@name", name);
    command.Parameters.AddWithValue("@phone", phone);

    try
    {
        connection.Open();

        int result = command.ExecuteNonQuery();

        Console.WriteLine(result);
    }
    finally
    {
        if (connection.State != ConnectionState.Closed)
            connection.Close();
    }
}

我不确定为什么使用Odbc命名空间对象,因为它听起来像是在使用MS-SQL。您应该使用System.Data.SqlClient命名空间中的对象。


您实际问题的答案很可能涉及执行类似于:

的脚本(而不是存储过程)
DECLARE @RC int
DECLARE @name varchar(50)
DECLARE @phone varchar(50)

-- TODO: Set parameter values here.

EXECUTE @RC = spFoo
   @name,
   @phone
GO

不推荐使用。