2

我有这个问题,我需要为我的存储过程设置“可选”参数才能正常工作。例如,我有这个:

CREATE PROCEDURE [dbo].[Search]
(
 @StartTime datetime = NULL,
 @EndTime datetime = NULL,
 @CustomerEmail nvarchar(255) = NULL,
 @OrderStatusID int
)

现在,在我的 .net 网站中,我有一个类似的示例,请记住,参数可能只有一个,也可能全部都有:

commAdvanced.Parameters.Add("@StartTime", SqlDbType.DateTime).Value = startDate;
commAdvanced.Parameters.Add("@EndTime", SqlDbType.DateTime).Value = endDate;
commAdvanced.Parameters.Add("@CustomerEmail", SqlDbType.nvarchar).Value = null;
commAdvanced.Parameters.Add("@OrderStatusID", SqlDbType.Int).Value = null;

这是查询:

SELECT * FROM Order 
WHERE CreatedOn > CAST(@StartTime as datetime) 
  AND CreatedOn < CAST(@EndTime as datetime)
  AND Order.OrderStatusID = @OrderStatusID 
  AND Order.CustomerEmail = @PaymentStatusID

当我这样做时,我没有得到任何记录,有人可以帮助我我需要改变什么。

4

5 回答 5

1

假设选择查询中有错字也许可以尝试

AND Order.CustomerEmail = ISNULL(@CustomerEmail, CustomerEmail)
And OrderStatusID = ISNULL(@OrderStatusID, OrderStatusID)

此外,您不需要将 @StartTime 等转换为日期时间。他们已经是那种类型了,不是吗?

于 2010-10-28T19:04:15.940 回答
0

您需要DBNull.Value为那些要保留 NULL 的参数(而不仅仅是 .NET null)传递:

commAdvanced.Parameters.Add("@CustomerEmail", SqlDbType.nvarchar).Value = DBNull.Value;
commAdvanced.Parameters.Add("@OrderStatusID", SqlDbType.Int).Value = DBNull.Value;

这应该可以解决问题。

另外:如果您指定类型为varcharor的参数nvarchar,我建议始终指定其长度。

于 2010-10-28T19:02:39.420 回答
0

根据您的问题,在 4 个参数中,一个或所有参数都可以传递给您的过程。并且您的查询在 where 子句中检查了所有列。因此,如果我理解正确,目前,在所有 4 个参数都传递有效数据之前,您不会获得任何记录。

试试这个,我只是构造一个查询然后执行它。我检查每个参数是否为空,并且只有非空的参数值包含在 where 子句中。

declare @sqlstring varchar(1000)

set @sqlstring = 'SELECT * FROM Order WHERE 1=1 '

if @StartTime <> null OR @StartTime <> '' 
BEGIN 
set @sqlstring = @sqlstring + 'AND CreatedOn > CAST(@StartTime as datetime) ' 
END 

if @EndTime <> null OR @EndTime <> '' 
BEGIN 
set @sqlstring = @sqlstring + 'AND CreatedOn < CAST(@EndTime as datetime) ' 
END 

if @OrderStatusID <> null OR @OrderStatusID <> '' 
BEGIN 
set @sqlstring = @sqlstring + 'AND OrderStatusID = @OrderStatusID ' 
END 

if @CustomerEmail <> null OR @CustomerEmail <> '' 
BEGIN 
set @sqlstring = @sqlstring + 'AND CustomerEmail > @CustomerEmail ' 
END 

print @sqlstring
Exec(@sqlstring)
于 2010-10-28T19:54:03.930 回答
0

我认为这很简单,因为您的查询不正确。

让我们以仅提供@StartTime 为例。您的查询将评估为:

SELECT * FROM Order  
WHERE CreatedOn > CAST(@StartTime as datetime)  
  AND CreatedOn < null
  AND Order.OrderStatusID = null
  AND Order.CustomerEmail = null

假设 ANSI NULL 为 ON,则与 null 相比,没有任何值返回真实结果,因此您的结果集为空。

我认为诺埃尔的答案最接近 - 我建议:

SELECT * FROM Order  
WHERE (@StartTime is null or CreatedOn > @StartTime)
  AND (@EndTime is null or CreatedOn < @EndTime)
  AND Order.OrderStatusID = isnull(@OrderStatusID, Order.OrderStatusID)
  AND Order.CustomerEmail = isnull(@CustomerEmail, Order.CustomerEmail)

marc_s 也是正确的——如果你明确地想将一个@参数值设置为 SQL null,将它设置为

commAdvanced.Parameters.Add("@CustomerEmail", SqlDbType.nvarchar).Value = DBNull.Value;          
commAdvanced.Parameters.Add("@OrderStatusID", SqlDbType.Int).Value = DBNull.Value;   

但是,由于您在存储过程中提供了 null 的默认值(@OrderStatusID - 错字除外?),您实际上根本不需要将这些参数添加到命令中。

于 2010-10-28T20:07:56.280 回答
0

请注意:可维护性的最佳解决方案可能不利于性能和可伸缩性(请注意,自 SQL Server 2008 以来,竞争环境已发生变化)。

这是一个相当大的话题,我建议您阅读Erland Sommarskog的 T-SQL 中的动态搜索条件。

于 2010-10-29T09:07:19.030 回答