Operadores lógicos OU AND em condição e ordem de condições em WHERE

33

Vamos examinar estas duas declarações:

IF (CONDITION 1) OR (CONDITION 2)
...

IF (CONDITION 3) AND (CONDITION 4)
...

Se CONDITION 1for TRUE, será CONDITION 2verificado?
Se CONDITION 3for FALSE, será CONDITION 4verificado?

E as condições em WHERE: o mecanismo do SQL Server otimiza todas as condições em uma WHEREcláusula? Os programadores devem colocar as condições na ordem certa para garantir que o otimizador do SQL Server as resolva da maneira correta ?

ADICIONADO:

Obrigado a Jack pelo link, surpresa do código t-sql:

IF  1/0 = 1 OR 1 = 1
      SELECT 'True' AS result
ELSE
      SELECT 'False' AS result


IF  1/0 = 1 AND 1 = 0
      SELECT 'True' AS result
ELSE
      SELECT 'False' AS result

Não há uma exceção Dividir por zero neste caso.

CONCLUSÃO:

Se C ++ / C # / VB está em curto-circuito, por que o SQL Server não pode ter?

Para realmente responder a isso, vamos dar uma olhada em como os dois trabalham com as condições. Todos os C ++ / C # / VB possuem curto-circuito definido nas especificações de linguagem para acelerar a execução do código. Por que se preocupar em avaliar as condições N OU quando o primeiro já é verdadeiro ou M e condições quando o primeiro já é falso.

Nós, como desenvolvedores, precisamos estar cientes de que o SQL Server funciona de maneira diferente. É um sistema baseado em custo. Para obter o plano de execução ideal para nossa consulta, o processador de consultas deve avaliar todas as condições where e atribuir um custo a ela. Esses custos são então avaliados como um todo para formar um limite que deve ser menor que o limite definido que o SQL Server possui para um bom plano. Se o custo for menor que o limite definido, o plano será usado; se não, todo o processo será repetido novamente com uma combinação diferente de custos de condição. O custo aqui é uma junção de varredura, busca ou mesclagem ou junção de hash, etc ... Por causa disso, o curto-circuito disponível em C ++ / C # / VB simplesmente não é possível. Você pode pensar que forçar o uso de índice em uma coluna conta como curto-circuito, mas não. Isso força apenas o uso desse índice e, com isso, reduz a lista de possíveis planos de execução. O sistema ainda é baseado em custos.

Como desenvolvedor, você deve estar ciente de que o SQL Server não provoca curto-circuito, como é feito em outras linguagens de programação e não há nada que você possa fazer para forçá-lo.

garik
fonte
De onde é o bloco de cotação final? Você poderia adicionar uma referência?
Nick Chammas

Respostas:

25

Não há garantia no SQL Server se ou em que ordem as instruções serão processadas em uma WHEREcláusula. A expressão única que permite um curto-circuito na declaração é CASE- WHEN. O seguinte é de uma resposta que eu publiquei no Stackoverflow:

Como o SQL Server provoca um curto-circuito na avaliação da condição

Faz quando parece, mas não da maneira que você pensa imediatamente.

Como desenvolvedor, você deve estar ciente de que o SQL Server não provoca curto-circuito, como é feito em outras linguagens de programação e não há nada que você possa fazer para forçá-lo .

Para mais detalhes, verifique o primeiro link na entrada do blog acima, que leva a outro blog:

O SQL Server está em curto-circuito?

O veredicto final? Bem, eu realmente não tenho uma ainda, mas provavelmente é seguro dizer que o único momento em que você pode garantir um curto-circuito específico é quando você expressa várias condições WHEN em uma expressão CASE. Com expressões booleanas padrão, o otimizador moverá as coisas como achar melhor com base nas tabelas, índices e dados que você está consultando.

MicSim
fonte
2
Aparentemente, há alguns casos de borda (ou um bug), onde ainda case não é seguro
Jack Douglas
1
Eu também demonstram um outro caso (ha!) Onde CASEbreaks: dba.stackexchange.com/questions/12941/...
Aaron Bertrand
0

SQL é uma linguagem de programação declarativa . Ao contrário, digamos, C ++, que é uma linguagem de programação imperativa .

Ou seja, você pode dizer o que deseja no resultado final, mas não pode ditar como o resultado está sendo executado, tudo depende do mecanismo.

A única maneira verdadeira de garantir "curto-circuito" (ou qualquer outro fluxo de controle ) WHEREé usar visualizações indexadas, tabelas temporárias e mecanismos semelhantes.

PS. Você também pode usar dicas de plano de execução (para "sugerir" ao mecanismo como executar uma consulta, quais índices usar e COMO usá-los), apenas pensei em mencioná-lo, enquanto estamos neste tópico ...

jitbit
fonte
-4

1) - OU (qualquer uma ou ambas as condições serão VERDADEIRAS)

se a condição 1 for VERDADEIRA, a condição 2 também será verificada, podendo ser VERDADEIRA ou FALSA

--AND (as duas condições devem ser VERDADEIRAS)

se a condição 1 for FALSE, a condição 2 não será verificada

Ranjith Kumar
fonte
"se a condição 1 for FALSE, a condição 2 não será verificada" Isso não é verdade. Veja a resposta acima . O SQL Server ainda pode avaliar a condição 2 porque não executa a avaliação de curto-circuito nas WHEREcláusulas.
Nick Chammas
-4

A única maneira de controlar como as condições da cláusula WHERE é usar colchetes para agrupá-los.

WHERE Col1 = 'Something' AND Col2 = 'Something' OR Col3 = 'Something' and Col4 = 'Something'

é muito diferente de

WHERE (Col1 = 'Something' AND Col2 = 'Something') OR (Col3 = 'Something' and Col4 = 'Something')
Mrdenny
fonte
Apenas curioso. Como essas duas condições são diferentes? Resultados diferentes, desempenho, plano de execução? Eu pensei que eles seriam equivalentes.
ypercubeᵀᴹ
Com o primeiro, você precisa combinar Col1, Col4 e Col2 ou Col3. Na segunda linha para combinar Col1 e Col2 ou você precisa combinar Col3 e Col4, mas Col1 e Col4 nunca precisarão ser avaliados juntos.
mrdenny
1
Não, você está errado. ANDtem precedência mais alta que OR. Ambos são equivalentes. O que você diz seria verdadeiro para a WHERE Col1 = x AND (Col2 = x OR Col3 = x) AND Col4 = xconsulta. Veja teste SQL-Fiddle
ypercubeᵀᴹ