如何将 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' 是正确的说法吗?不,不是。