代码之家  ›  专栏  ›  技术社区  ›  Terry

如何将空值传递给具有非空默认值的SQL Server存储过程参数

  •  0
  • Terry  · 技术社区  · 6 年前

    我在多租户数据库中有一个SQL Server存储过程。它被所有客户机使用,但由于我不同时更新所有客户机,所以我需要提供默认参数值,以便客户机在不传递参数时不会抛出错误。

    看起来是这样的:

    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 作为默认值,因为 无效的 是要传入(清除搜索索引)的有效值。但是,当我将参数分配给 DBNull.Value ,似乎存储过程 认为什么都不是 传递,然后存储过程在其逻辑中使用默认的“btr:noSearchUpdate”,不执行任何操作(而不是清除值)-如果分配dbnull,则!=下面的“btr;noSearchUpdate”的计算结果为false。

    CASE WHEN @pSearch01 != 'BTR:NOSEARCHUPDATE' THEN @pSearch01 ELSE pSearch01 END,

    此语句只是在“传入了某些内容(dbnull或value)”时尝试获取参数的值,否则将返回到相应db字段中的现有值。

    我指派 DBNull 使用以下代码:

    UpdateCommand.Parameters[ "@pSearch19" ].Value = DBNull.Value;
    

    所以问题是,我如何将“null”传递给存储过程,以便它使用它作为值,而不是简单地使用默认值“btr:nosearchupdate”?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Brian Vitaliy Nesterenko    6 年前

    null 是要传递的有效值,它不会被默认参数值覆盖。我无法在T-SQL或ADO.NET中重新设置此行为。

    例如

    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
    

    但看起来这是一个简单的空比较和三值逻辑。

    考虑:

    declare @pSearch01 nvarchar(200) = null
    select CASE WHEN @pSearch01 != 'BTR:NOSEARCHUPDATE' then 1 else 0 end
    

    那又是什么呢?是 null != 'BTR:NOSEARCHUPDATE' 一个真实的陈述?不,不是。