MS-SQL 存储过程不适用于空参数
MS-SQL Stored Procedure doesn't work with empty params
我有一个包含输入 'name' 和 'phone' 的表单。
当它们有值时,一切正常:使用存储过程将记录插入数据库,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 上工作
我希望用户无需任何输入即可创建记录。
为什么这在 Management Studio 中有效,但在应用程序中却无效?
更新: 我在存储过程中的参数中添加了默认值,但没有用;我在代码中给出了空字符串 "NULL" 作为值,仍然没有成功。这是服务器设置还是不允许空变量的设置?
从代码调用存储过程时,应在命令中使用参数 属性。试试这个:
String sp = "spFoo";
command.Parameters.Add("@name", "test name");
command.Parameters.Add("@phone", "test phone");
正如 JimmyV 所说,您应该使用 command.Parameters.Add 方法来设置您的参数,只要未指定参数值就传入 null。要解决您对错误“过程或函数 'spFoo' 需要参数‘@name’,未提供”的评论,您还需要修改存储过程以在未提供参数时使用默认值(例如 null):
CREATE PROCEDURE MyStoredProcedure
@foo int = null
AS
BEGIN
...
END
很抱歉没有在上面添加评论 post。声望不够!
您不应该像现在这样调用存储过程。您应该使用参数。您的代码容易受到 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
不推荐。
您需要从存储过程中删除 SET NOCOUNT ON;
。
Stops the message that shows the count of the number of rows affected by a Transact-SQL statement or stored procedure from being returned as part of the result set.
正如其他人指出的那样,您也应该对查询进行参数化,但是 -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());
}
}
我有一个包含输入 'name' 和 'phone' 的表单。
当它们有值时,一切正常:使用存储过程将记录插入数据库,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 上工作
我希望用户无需任何输入即可创建记录。
为什么这在 Management Studio 中有效,但在应用程序中却无效?
更新: 我在存储过程中的参数中添加了默认值,但没有用;我在代码中给出了空字符串 "NULL" 作为值,仍然没有成功。这是服务器设置还是不允许空变量的设置?
从代码调用存储过程时,应在命令中使用参数 属性。试试这个:
String sp = "spFoo";
command.Parameters.Add("@name", "test name");
command.Parameters.Add("@phone", "test phone");
正如 JimmyV 所说,您应该使用 command.Parameters.Add 方法来设置您的参数,只要未指定参数值就传入 null。要解决您对错误“过程或函数 'spFoo' 需要参数‘@name’,未提供”的评论,您还需要修改存储过程以在未提供参数时使用默认值(例如 null):
CREATE PROCEDURE MyStoredProcedure
@foo int = null
AS
BEGIN
...
END
很抱歉没有在上面添加评论 post。声望不够!
您不应该像现在这样调用存储过程。您应该使用参数。您的代码容易受到 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
不推荐。
您需要从存储过程中删除 SET NOCOUNT ON;
。
Stops the message that shows the count of the number of rows affected by a Transact-SQL statement or stored procedure from being returned as part of the result set.
正如其他人指出的那样,您也应该对查询进行参数化,但是 -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());
}
}