sql参数可以是可选的

发布于 2024-09-29 10:01:53 字数 908 浏览 4 评论 0原文

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

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

我没有得到当我这样做时记录,有人可以帮我我需要改变什么吗?

I have this problem where I need to set "optional" parameters for my stored procedure to work fine.
For example, I have this:

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

Now, in my .net website I have this like an example, please keep in mind that there can be only one parameter or there might be all of them:

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;

And this is the query:

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

I am getting no records when I am doing that, can someone please help me what do I need to change.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

你如我软肋 2024-10-06 10:01:54

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

这是一个相当大的主题,我建议您阅读 T-SQL 中的动态搜索条件厄兰·索马斯科格。

Be warned: the best solution for maintainability may not be good for performance and scalability (and note the playing field has changed since SQL Server 2008).

This is quite a big topic and I recommend you read Dynamic Search Conditions in T-SQL by Erland Sommarskog.

药祭#氼 2024-10-06 10:01:53

假设选择查询中存在拼写错误,可以尝试

AND Order.CustomerEmail = ISNULL(@CustomerEmail, CustomerEmail)
并且 OrderStatusID = ISNULL(@OrderStatusID, OrderStatusID)

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

Assuming there is a typo in the select query perhaps try

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

Also you don't need to cast @StartTime etc. to datetime. They are already of that type, no?

单调的奢华 2024-10-06 10:01:53

根据您的问题,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)

According to your question, out of 4 parameters either one or all parameters could be passed to your procedure. And your query has all the columns checked for in the where clause. So if I understand you right, currently, you will not get any records until all 4 parameters are passed with valid data.

Try this, I am simply constructing a query and then executing it. I check for each of the parameters for nulls and only the parameter values that are not null are included in the where clause.

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)
少女的英雄梦 2024-10-06 10:01:53

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

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

这应该可以解决问题。

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

You need to pass in DBNull.Value for those parameter you want to leave NULL (not just the .NET null) :

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

This should do the trick.

Also: if you specify a parameter of type varchar or nvarchar, I would recommend to always specify its length.

緦唸λ蓇 2024-10-06 10:01:53

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

让我们以仅提供@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 相比没有值返回 true 结果,因此您的结果集为空。

我认为 Noel 的答案最接近 - 我建议:

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 - 拼写错误?),您实际上根本不需要将这些参数添加到命令中。

I think this is simpy down to your query being incorrect.

Lets take the example of supplying only @StartTime. Your query would evaluate to:

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

Assuming ANSI NULLs are ON, there is no value which when compared to null returns a true result, hence your empty result set.

I think Noel's answer is closest - I would suggest:

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 is also correct - if you explicitly want to set an @ parameter value to SQL null, set it as

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

However, because you have supplied default values of null in your stored proc (except @OrderStatusID - typo?), you don't actually need to add these parameters to the command at all.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文