SqlParameter "disappears" 什么时候赋值为null?
SqlParameter "disappears" when assigned a value of null?
我最近偶然发现了以下问题:
将 null
分配给 SqlParameter 的值 属性 似乎会导致从查询中省略参数而不是传递 NULL
。当存储过程没有参数的默认值时,这会导致潜在的误导性错误消息。
我有一个数据库 table,其中有一列接受 NULL
。
USE [TheDatabase]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[TheTable](
[Id] [int] IDENTITY(1,1) NOT NULL,
[TheValue] [varchar](50) NULL,
CONSTRAINT [PK_TheTable] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
table 是使用存储过程填充的。请注意,以列为目标的参数未指定默认值。
USE [TheDatabase]
GO
CREATE PROCEDURE TheStoredProcedure
@TheValue varchar(50)
AS
BEGIN
INSERT INTO TheTable (TheValue) VALUES (@TheValue);
END
GO
使用值和 NULL
执行存储过程都很好:
USE [TheDatabase]
GO
EXEC [dbo].[TheStoredProcedure] @TheValue = 'A string for Algernon'
GO
EXEC [dbo].[TheStoredProcedure] @TheValue = NULL
GO
我运行下面的代码:
using System;
using System.Data;
using System.Data.SqlClient;
class Program
{
static void Main(string[] args)
{
ExecuteStoredProcedure("A string for Algernon");
ExecuteStoredProcedure(DBNull.Value);
ExecuteStoredProcedure(null);
Console.ReadKey();
}
private static void ExecuteStoredProcedure(object value)
{
using (var connection = new SqlConnection("Server=TheServer;Database=TheDatabase;Persist Security Info=False;Integrated Security=true;"))
{
connection.Open();
using (var sqlCommand = new SqlCommand("TheStoredProcedure", connection) {CommandType = CommandType.StoredProcedure})
{
sqlCommand.Parameters.Add(new SqlParameter("@TheValue", SqlDbType.VarChar, 50) {Value = value});
try
{
sqlCommand.ExecuteNonQuery();
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
Console.WriteLine(DateTime.Now);
}
}
前两个方法调用 运行 没问题:第一个将字符串添加到 table,第二个添加一个 NULL
,但调用 ExecuteStoredProcedure()
时使用 null
导致以下错误:
System.Data.SqlClient.SqlException (0x80131904): Procedure or function 'TheStoredProcedure' expects parameter '@TheValue', which was not supplied.
从文档看来,当您希望在存储过程中使用参数的默认值时,您应该使用 null
。
This property can be set to null or Value. Use Value to send a NULL value as the value of the parameter. Use null or do not set Value to use the default value for the parameter.
因为我的参数 没有 默认值,所以会出现某种错误。但是,我们得到的结果似乎具有误导性:一个错误表明该参数未在数据库端收到,而不是一个错误表明该参数具有意外值(或者更确切地说:缺少值)。
或者这实际上是预期的行为,将值设置为 null
有效地排除了在执行命令时将参数传递给服务器的行为?
2010 年 1 月更新
文档已更新:
This property can be set to null
or DBNull.Value
. Use DBNull.Value
to send a NULL value as the value of the parameter. Use null
or do not set Value to use the default value for the parameter.
可能不crystal清楚,但至少是明确的。
这里的关键是,如果 SqlParamer
对象的值 属性 具有 null
,那么为存储过程定义的参数的默认值就会起作用,并且我只能假设这是通过从查询执行中省略它来实现的 "behind the scenes"。
我想这里要吸取的教训是始终使用可选参数的默认值定义存储过程。
-S
此 属性 可以设置为空或 DBNull.Value。使用 DBNull.Value 发送 NULL 值作为参数值。 使用 null 或不设置 Value 以使用参数的默认值。
所以对于value = null
你必须设置你的参数的默认值。
CREATE PROCEDURE TheStoredProcedure
@TheValue varchar(50) = NULL
如果要将 NULL 传递给存储过程,请不要 将值设置为 null
文档几乎是正确的。在语句中:
Use Value to send a NULL value as the value of the parameter.
link指向DbNull.Value。这是文档错误
传递 null
而不是 DbNull.Value
意味着您想使用存储过程的默认参数。那部分文档是正确的:
Use null or do not set Value to use the default value for the parameter.
更新
我刚刚为此添加了 a Github issue
我最近偶然发现了以下问题:
将 null
分配给 SqlParameter 的值 属性 似乎会导致从查询中省略参数而不是传递 NULL
。当存储过程没有参数的默认值时,这会导致潜在的误导性错误消息。
我有一个数据库 table,其中有一列接受 NULL
。
USE [TheDatabase]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[TheTable](
[Id] [int] IDENTITY(1,1) NOT NULL,
[TheValue] [varchar](50) NULL,
CONSTRAINT [PK_TheTable] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
table 是使用存储过程填充的。请注意,以列为目标的参数未指定默认值。
USE [TheDatabase]
GO
CREATE PROCEDURE TheStoredProcedure
@TheValue varchar(50)
AS
BEGIN
INSERT INTO TheTable (TheValue) VALUES (@TheValue);
END
GO
使用值和 NULL
执行存储过程都很好:
USE [TheDatabase]
GO
EXEC [dbo].[TheStoredProcedure] @TheValue = 'A string for Algernon'
GO
EXEC [dbo].[TheStoredProcedure] @TheValue = NULL
GO
我运行下面的代码:
using System;
using System.Data;
using System.Data.SqlClient;
class Program
{
static void Main(string[] args)
{
ExecuteStoredProcedure("A string for Algernon");
ExecuteStoredProcedure(DBNull.Value);
ExecuteStoredProcedure(null);
Console.ReadKey();
}
private static void ExecuteStoredProcedure(object value)
{
using (var connection = new SqlConnection("Server=TheServer;Database=TheDatabase;Persist Security Info=False;Integrated Security=true;"))
{
connection.Open();
using (var sqlCommand = new SqlCommand("TheStoredProcedure", connection) {CommandType = CommandType.StoredProcedure})
{
sqlCommand.Parameters.Add(new SqlParameter("@TheValue", SqlDbType.VarChar, 50) {Value = value});
try
{
sqlCommand.ExecuteNonQuery();
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
Console.WriteLine(DateTime.Now);
}
}
前两个方法调用 运行 没问题:第一个将字符串添加到 table,第二个添加一个 NULL
,但调用 ExecuteStoredProcedure()
时使用 null
导致以下错误:
System.Data.SqlClient.SqlException (0x80131904): Procedure or function 'TheStoredProcedure' expects parameter '@TheValue', which was not supplied.
从文档看来,当您希望在存储过程中使用参数的默认值时,您应该使用 null
。
This property can be set to null or Value. Use Value to send a NULL value as the value of the parameter. Use null or do not set Value to use the default value for the parameter.
因为我的参数 没有 默认值,所以会出现某种错误。但是,我们得到的结果似乎具有误导性:一个错误表明该参数未在数据库端收到,而不是一个错误表明该参数具有意外值(或者更确切地说:缺少值)。
或者这实际上是预期的行为,将值设置为 null
有效地排除了在执行命令时将参数传递给服务器的行为?
2010 年 1 月更新
文档已更新:
This property can be set to
null
orDBNull.Value
. UseDBNull.Value
to send a NULL value as the value of the parameter. Usenull
or do not set Value to use the default value for the parameter.
可能不crystal清楚,但至少是明确的。
这里的关键是,如果 SqlParamer
对象的值 属性 具有 null
,那么为存储过程定义的参数的默认值就会起作用,并且我只能假设这是通过从查询执行中省略它来实现的 "behind the scenes"。
我想这里要吸取的教训是始终使用可选参数的默认值定义存储过程。
-S
此 属性 可以设置为空或 DBNull.Value。使用 DBNull.Value 发送 NULL 值作为参数值。 使用 null 或不设置 Value 以使用参数的默认值。
所以对于value = null
你必须设置你的参数的默认值。
CREATE PROCEDURE TheStoredProcedure
@TheValue varchar(50) = NULL
如果要将 NULL 传递给存储过程,请不要 将值设置为 null
文档几乎是正确的。在语句中:
Use Value to send a NULL value as the value of the parameter.
link指向DbNull.Value。这是文档错误
传递 null
而不是 DbNull.Value
意味着您想使用存储过程的默认参数。那部分文档是正确的:
Use null or do not set Value to use the default value for the parameter.
更新
我刚刚为此添加了 a Github issue