如何将 null 传递给具有 NON-NULL 默认值的 SQL 服务器存储过程参数
How to pass null to SQL Server stored procedure param with NON-NULL default value
我在多租户数据库中有一个 SQL 服务器存储过程。它被所有客户端使用,但由于我不会同时更新它们,所以我需要提供默认参数值,以便客户端在没有传入参数时不会抛出错误。
看起来像这样:
ALTER PROCEDURE [dbo].[sp_UpdateSearchValues]
@pAuthID NVARCHAR(255),
@pgKey INT,
@pSearch01 NVARCHAR(255) = 'BTR:NOSEARCHUPDATE',
@pSearch02 NVARCHAR(255) = 'BTR:NOSEARCHUPDATE',
..
@pSearch30 NVARCHAR(255) = 'BTR:NOSEARCHUPDATE'
我不能使用 null
作为默认值,因为 null
是一个可以传入的有效值(以清除搜索索引)。但是,当我将参数分配给 DBNull.Value
时,似乎存储过程 认为没有任何内容被 传递,然后存储过程在其逻辑中使用默认值 'BTR:NOSEARCHUPDATE'什么也不做(而不是清除值)- 如果我分配 DBNull,下面的 != 'BTR;NOSEARCHUPDATE' 计算为 false。
CASE WHEN @pSearch01 != 'BTR:NOSEARCHUPDATE' THEN @pSearch01 ELSE pSearch01 END,
这条语句只是试图获取参数if 'something was passed in (DBNull or value)'的值,否则回退到相应db字段中已有的值。
我使用以下代码分配 DBNull
:
UpdateCommand.Parameters[ "@pSearch19" ].Value = DBNull.Value;
所以问题是,我如何将 'null' 传递给存储过程,以便它使用它作为值而不是简单地使用默认值 'BTR:NOSEARCHUPDATE'?
null
是要传递的有效值,它不会被默认参数值覆盖。我无法在 T-SQL 或 ADO.NET.
中重现此行为
EG
create or alter procedure [dbo].[sp_UpdateSearchValues]
@pAuthID nvarchar(255),
@pgKey int,
@pSearch01 nvarchar(255) = 'BTR:NOSEARCHUPDATE',
@pSearch02 nvarchar(255) = 'BTR:NOSEARCHUPDATE',
@pSearch30 nvarchar(255) = 'BTR:NOSEARCHUPDATE'
as
begin
select @pSearch01 search01
end
然后在 .NET 中
using (var con = new SqlConnection("server=.;database=tempdb;integrated security=true"))
{
con.Open();
SqlCommand cmd = con.CreateCommand();
cmd.CommandText = "sp_UpdateSearchValues";
cmd.CommandType = System.Data.CommandType.StoredProcedure;
var pAuthID = cmd.Parameters.Add("@pAuthID", SqlDbType.NVarChar,255 );
var pgKey = cmd.Parameters.Add("@pgKey", SqlDbType.Int);
var pSearch01 = cmd.Parameters.Add("@pSearch01", SqlDbType.NVarChar, 255);
pAuthID.Value = "a";
pgKey.Value = 1;
pSearch01.Value = DBNull.Value;
var r = cmd.ExecuteScalar();
Console.WriteLine($"{r} {r.GetType().Name}");
Console.ReadKey();
}
产出
DBNull
但看起来这是空值比较和 3 值逻辑的简单情况。
考虑:
declare @pSearch01 nvarchar(200) = null
select CASE WHEN @pSearch01 != 'BTR:NOSEARCHUPDATE' then 1 else 0 end
那是什么 return? null != 'BTR:NOSEARCHUPDATE'
是正确的说法吗?不,不是。
我在多租户数据库中有一个 SQL 服务器存储过程。它被所有客户端使用,但由于我不会同时更新它们,所以我需要提供默认参数值,以便客户端在没有传入参数时不会抛出错误。
看起来像这样:
ALTER PROCEDURE [dbo].[sp_UpdateSearchValues]
@pAuthID NVARCHAR(255),
@pgKey INT,
@pSearch01 NVARCHAR(255) = 'BTR:NOSEARCHUPDATE',
@pSearch02 NVARCHAR(255) = 'BTR:NOSEARCHUPDATE',
..
@pSearch30 NVARCHAR(255) = 'BTR:NOSEARCHUPDATE'
我不能使用 null
作为默认值,因为 null
是一个可以传入的有效值(以清除搜索索引)。但是,当我将参数分配给 DBNull.Value
时,似乎存储过程 认为没有任何内容被 传递,然后存储过程在其逻辑中使用默认值 'BTR:NOSEARCHUPDATE'什么也不做(而不是清除值)- 如果我分配 DBNull,下面的 != 'BTR;NOSEARCHUPDATE' 计算为 false。
CASE WHEN @pSearch01 != 'BTR:NOSEARCHUPDATE' THEN @pSearch01 ELSE pSearch01 END,
这条语句只是试图获取参数if 'something was passed in (DBNull or value)'的值,否则回退到相应db字段中已有的值。
我使用以下代码分配 DBNull
:
UpdateCommand.Parameters[ "@pSearch19" ].Value = DBNull.Value;
所以问题是,我如何将 'null' 传递给存储过程,以便它使用它作为值而不是简单地使用默认值 'BTR:NOSEARCHUPDATE'?
null
是要传递的有效值,它不会被默认参数值覆盖。我无法在 T-SQL 或 ADO.NET.
EG
create or alter procedure [dbo].[sp_UpdateSearchValues]
@pAuthID nvarchar(255),
@pgKey int,
@pSearch01 nvarchar(255) = 'BTR:NOSEARCHUPDATE',
@pSearch02 nvarchar(255) = 'BTR:NOSEARCHUPDATE',
@pSearch30 nvarchar(255) = 'BTR:NOSEARCHUPDATE'
as
begin
select @pSearch01 search01
end
然后在 .NET 中
using (var con = new SqlConnection("server=.;database=tempdb;integrated security=true"))
{
con.Open();
SqlCommand cmd = con.CreateCommand();
cmd.CommandText = "sp_UpdateSearchValues";
cmd.CommandType = System.Data.CommandType.StoredProcedure;
var pAuthID = cmd.Parameters.Add("@pAuthID", SqlDbType.NVarChar,255 );
var pgKey = cmd.Parameters.Add("@pgKey", SqlDbType.Int);
var pSearch01 = cmd.Parameters.Add("@pSearch01", SqlDbType.NVarChar, 255);
pAuthID.Value = "a";
pgKey.Value = 1;
pSearch01.Value = DBNull.Value;
var r = cmd.ExecuteScalar();
Console.WriteLine($"{r} {r.GetType().Name}");
Console.ReadKey();
}
产出
DBNull
但看起来这是空值比较和 3 值逻辑的简单情况。
考虑:
declare @pSearch01 nvarchar(200) = null
select CASE WHEN @pSearch01 != 'BTR:NOSEARCHUPDATE' then 1 else 0 end
那是什么 return? null != 'BTR:NOSEARCHUPDATE'
是正确的说法吗?不,不是。