sql参数,可以是可选的

时间:2010-10-28 18:53:30

标签: .net sql procedure

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

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

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

5 个答案:

答案 0 :(得分:1)

假设select查询中存在拼写错误,请尝试

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

此外,您无需将@StartTime等转换为datetime。他们已经属于那种类型,不是吗?

答案 1 :(得分:0)

您需要传入DBNull.Value以获取要留给NULL的参数(不仅仅是.NET null):

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

这应该可以解决问题。

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

答案 2 :(得分: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)

答案 3 :(得分: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;   

但是,因为您在存储的proc 中提供了默认值null(除了@OrderStatusID - 错误?),所以实际上并不需要将这些参数添加到命令中。< / p>

答案 4 :(得分:0)

警告:可维护性的最佳解决方案可能不利于性能和可伸缩性(并注意自SQL Server 2008以来游戏领域已发生变化)。

这是一个非常大的话题,我建议你阅读Erland Sommarskog的Dynamic Search Conditions in T-SQL