Параметры SQL, которые могут быть необязательными - PullRequest
2 голосов
/ 28 октября 2010

У меня есть проблема, когда мне нужно установить «необязательные» параметры для моей хранимой процедуры, чтобы работать нормально.Например, у меня есть это:

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 ]

1 голос
/ 28 октября 2010

Если в запросе на выбор есть опечатка, возможно, попробуйте

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

Также вам не нужно приводить @StartTime и т. Д. К datetime.Они уже такого типа, нет?

0 голосов
/ 29 октября 2010

Имейте в виду: лучшее решение для удобства обслуживания может не подходить для производительности и масштабируемости (и обратите внимание, что игровое поле изменилось с SQL Server 2008).

Это довольно большая тема, и я рекомендую вам прочитать Условия динамического поиска в T-SQL Эрланда Соммарского.

0 голосов
/ 29 октября 2010

Я думаю, это просто, если ваш запрос неверен.

Давайте рассмотрим пример предоставления только @StartTime.Ваш запрос оценивается следующим образом:

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

Если предположить, что значения ANSI 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 - typo?) , вам вообще не нужно добавлять эти параметры в команду.

0 голосов
/ 28 октября 2010

По вашему вопросу, из 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 голосов
/ 28 октября 2010

Вам нужно ввести DBNull.Value для тех параметров, которые вы хотите оставить NULL (не только .NET null):

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

Это должно помочь.

Также: если вы укажете параметр типа varchar или nvarchar, я бы рекомендовал всегда указывать его длину.

...