2010-10-28 64 views
2

我有这个问题,我需要为我的存储过程设置“可选”参数工作正常。 例如,我有这样的:现在可以选择的sql参数

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 

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

+1

哪里'@ PaymentStatusID'来自于你的'SELECT'声明? – Oded 2010-10-28 18:58:55

回答

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) 
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的参数,我会建议总是指定其长度。

1

假设有在选择查询一个错字也许尝试

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

你也不必@starttime等转换为日期时间。他们已经是那种类型了,不是吗?

0

我认为这简单到你的查询不正确。

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

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

假设ANSI空值是ON,没有值比较空的时候返回真值结果,因此你的查询结果为空。

我想诺埃尔的答案是最接近的 - 我建议:

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 - typo?),你根本不需要将这些参数添加到命令中。

0

被警告:可维护性最好的解决方案可能不利于性能和可扩展性(并注意因为SQL Server 2008中的公平的竞争环境发生了变化)。

这是一个相当大的话题,我建议你通过厄兰Sommarskog阅读Dynamic Search Conditions in T-SQL