É possível usar uma cláusula IF dentro de uma cláusula WHERE no MS SQL?
Exemplo:
WHERE
IF IsNumeric(@OrderNumber) = 1
OrderNumber = @OrderNumber
ELSE
OrderNumber LIKE '%' + @OrderNumber + '%'
É possível usar uma cláusula IF dentro de uma cláusula WHERE no MS SQL?
Exemplo:
WHERE
IF IsNumeric(@OrderNumber) = 1
OrderNumber = @OrderNumber
ELSE
OrderNumber LIKE '%' + @OrderNumber + '%'
Respostas:
Use uma instrução CASE
UPDATE: A sintaxe anterior (conforme apontado por algumas pessoas) não funciona. Você pode usar o CASE da seguinte maneira:
WHERE OrderNumber LIKE
CASE WHEN IsNumeric(@OrderNumber) = 1 THEN
@OrderNumber
ELSE
'%' + @OrderNumber
END
Ou você pode usar uma declaração IF como @ NJ Reed aponta.
CASE
é a solução apropriada na maioria dos casos. No meu caso, eu queria mudar o operador de comparação e, portanto, usei a próxima abordagem.
Você deve conseguir fazer isso sem nenhum IF ou CASE
WHERE
(IsNumeric(@OrderNumber) AND
(CAST OrderNumber AS VARCHAR) = (CAST @OrderNumber AS VARCHAR)
OR
(NOT IsNumeric(@OrderNumber) AND
OrderNumber LIKE ('%' + @OrderNumber))
Dependendo do tipo de SQL, pode ser necessário ajustar as transmissões no número do pedido para um INT ou VARCHAR, dependendo do suporte a transmissões implícitas.
Essa é uma técnica muito comum em uma cláusula WHERE. Se você deseja aplicar alguma lógica "SE" na cláusula WHERE, tudo o que você precisa fazer é adicionar a condição extra com um AND booleano à seção em que ela precisa ser aplicada.
Você não precisa de uma declaração SE.
WHERE
(IsNumeric(@OrderNumber) = 1 AND OrderNumber = @OrderNumber)
OR (IsNumeric(@OrderNumber) = 0 AND OrderNumber LIKE '%' + @OrderNumber + '%')
where (@AdmUserId is null or CurrentOrder.CustomerAdmUserId = @AdmUserId)
Ou único filtro se IncludeDeleted = 0: where (@IncludeDeleted = 1 or ItemObject.DeletedFlag = 0)
Não há uma boa maneira de fazer isso no SQL. Algumas abordagens que eu já vi:
1) Use CASE combinado com operadores booleanos:
WHERE
OrderNumber = CASE
WHEN (IsNumeric(@OrderNumber) = 1)
THEN CONVERT(INT, @OrderNumber)
ELSE -9999 -- Some numeric value that just cannot exist in the column
END
OR
FirstName LIKE CASE
WHEN (IsNumeric(@OrderNumber) = 0)
THEN '%' + @OrderNumber
ELSE ''
END
2) Use IFs fora do SELECT
IF (IsNumeric(@OrderNumber)) = 1
BEGIN
SELECT * FROM Table
WHERE @OrderNumber = OrderNumber
END ELSE BEGIN
SELECT * FROM Table
WHERE OrderNumber LIKE '%' + @OrderNumber
END
3) Usando uma cadeia longa, componha sua instrução SQL condicionalmente e use EXEC
A terceira abordagem é hedionda, mas é quase a única coisa que funciona se você tiver várias condições variáveis como essa.
IF...ELSE...
condicionais em booleanos AND
e OR
s, como na resposta @ njr101 acima. Desvantagem para ^ desta abordagem é que ele pode ser cérebro-fryingly difícil se você tiver muitos IF
s', ou se você tem muitos que são aninhados
Use uma instrução CASE em vez de IF.
Você deseja a instrução CASE
WHERE OrderNumber LIKE
CASE WHEN IsNumeric(@OrderNumber)=1 THEN @OrderNumber ELSE '%' + @OrderNumber END
Eu acho que onde ... como / = ... caso ... então ... pode trabalhar com booleanos. Estou usando o T-SQL.
Cenário: Digamos que você deseja obter os hobbies da Pessoa-30 se bool for falso e os hobbies da Pessoa-42 se bool for verdadeiro. (De acordo com alguns, as pesquisas por hobby compreendem mais de 90% dos ciclos de computação dos negócios, portanto, preste muita atenção.)
CREATE PROCEDURE sp_Case
@bool bit
AS
SELECT Person.Hobbies
FROM Person
WHERE Person.ID =
case @bool
when 0
then 30
when 1
then 42
end;
WHERE (IsNumeric (@OrderNumber) <> 1 OU OrderNumber = @OrderNumber) AND (IsNumber (@OrderNumber) = 1 OU OrderNumber LIKE '%' + @OrderNumber + '%')
IF P THEN Q ELSE R
<=>
( ( NOT P ) OR Q ) AND ( P OR R )
Instrução CASE é a melhor opção do que SE sempre.
WHERE vfl.CreatedDate >= CASE WHEN @FromDate IS NULL THEN vfl.CreatedDate ELSE @FromDate END
AND vfl.CreatedDate<=CASE WHEN @ToDate IS NULL THEN vfl.CreatedDate ELSE @ToDate END
WHERE OrderNumber LIKE CASE WHEN IsNumeric(@OrderNumber) = 1 THEN @OrderNumber ELSE '%' + @OrderNumber END
No caso de linha, a condição funcionará corretamente.
O exemplo a seguir executa uma consulta como parte da expressão booleana e, em seguida, executa blocos de instrução ligeiramente diferentes com base no resultado da expressão booleana. Cada bloco de instrução começa com BEGIN e termina com END.
USE AdventureWorks2012;
GO
DECLARE @AvgWeight decimal(8,2), @BikeCount int
IF
(SELECT COUNT(*) FROM Production.Product WHERE Name LIKE 'Touring-3000%' ) > 5
BEGIN
SET @BikeCount =
(SELECT COUNT(*)
FROM Production.Product
WHERE Name LIKE 'Touring-3000%');
SET @AvgWeight =
(SELECT AVG(Weight)
FROM Production.Product
WHERE Name LIKE 'Touring-3000%');
PRINT 'There are ' + CAST(@BikeCount AS varchar(3)) + ' Touring-3000 bikes.'
PRINT 'The average weight of the top 5 Touring-3000 bikes is ' + CAST(@AvgWeight AS varchar(8)) + '.';
END
ELSE
BEGIN
SET @AvgWeight =
(SELECT AVG(Weight)
FROM Production.Product
WHERE Name LIKE 'Touring-3000%' );
PRINT 'Average weight of the Touring-3000 bikes is ' + CAST(@AvgWeight AS varchar(8)) + '.' ;
END ;
GO
Usando instruções IF ... ELSE aninhadas O exemplo a seguir mostra como uma instrução IF… ELSE pode ser aninhada dentro de outra. Defina a variável @Number como 5, 50 e 500 para testar cada instrução.
DECLARE @Number int
SET @Number = 50
IF @Number > 100
PRINT 'The number is large.'
ELSE
BEGIN
IF @Number < 10
PRINT 'The number is small'
ELSE
PRINT 'The number is medium'
END ;
GO
No servidor sql, eu tinha o mesmo problema. Eu queria usar uma instrução e apenas se o parâmetro for falso e, em verdadeiro, eu tinha que mostrar os valores verdadeiro e falso, então usei dessa maneira
(T.IsPublic = @ShowPublic or @ShowPublic = 1)
If @LstTransDt is Null
begin
Set @OpenQty=0
end
else
begin
Select @OpenQty=IsNull(Sum(ClosingQty),0)
From ProductAndDepotWiseMonitoring
Where Pcd=@PCd And PtpCd=@PTpCd And TransDt=@LstTransDt
end
Veja se isso ajuda.
USE AdventureWorks2012;
GO
IF
(SELECT COUNT(*) FROM Production.Product WHERE Name LIKE 'Touring-3000%' ) > 5
PRINT 'There are more than 5 Touring-3000 bicycles.'
ELSE PRINT 'There are 5 or less Touring-3000 bicycles.' ;
GO