48 votes

Test d'inégalité en T-SQL

Je viens de rencontrer ce problème dans une clause WHERE :

AND NOT (t.id = @id)

Comment cela se compare-t-il avec :

AND t.id != @id

Ou avec :

AND t.id <> @id

J'écrirais toujours ce dernier moi-même, mais il est clair que quelqu'un d'autre pense différemment. L'un va-t-il être plus performant que l'autre ? Je sais qu'en utilisant <> ou != va anéantir tous les espoirs que j'avais d'utiliser un index, mais sûrement la première approche ci-dessus souffrira-t-elle du même problème ?

1 votes

1 votes

La syntaxe NOT (...) est une mauvaise pratique lorsque le code peut être facilement infirmé pour être dans l'affirmatif ou dans le négatif. de Morgan d pour des raisons de lisibilité. Par exemple, vous ne devriez pas écrire du code comme IF (NOT(A)) THEN [x] ELSE [y] END alors que vous pourriez simplement écrire IF (A) THEN [y] ELSE [x] END

44voto

SQLMenace Points 68670

Ces trois-là auront exactement le même plan d'exécution

declare @id varchar(40)
select @id = '172-32-1176'

select * from authors
where au_id <> @id

select * from authors
where au_id != @id

select * from authors
where not (au_id = @id)

Cela dépendra aussi de la sélectivité de l'indice lui-même, bien sûr. J'utilise moi-même toujours au_id <> @id

6 votes

Comment ces clauses traitent-elles les nuls ? Sont-elles toutes équivalentes ?

2 votes

@FistOfFury, Comparer avec NULL renvoie toujours NULL et empêche les correspondances (sauf si vous a modifié le paramètre ANSI NULLs ), vous n'obtiendrez donc jamais d'enregistrements où au_id est nulle, et vous n'obtiendrez jamais d'enregistrements si @id est nulle. Dans ce cas, vous devez réellement écrire WHERE ... IS NULL o WHERE ... IS NOT NULL Cela m'aide à penser à NULL comme "inconnu", cela a du sens : vous ne savez pas si @id est la même chose qu'une valeur inconnue ! tl;dr Oui ils sont équivalents même dans le cas de NULLs.

30voto

DannySmurf Points 421

Notez que l'opérateur != n'est pas un standard SQL. Si vous voulez que votre code soit portable (c'est-à-dire, si vous y tenez), utilisez <> à la place.

12voto

Juste un petit ajustement pour ceux qui arrivent plus tard :

L'opérateur d'égalité génère une valeur inconnue lorsqu'il y a un null et la valeur inconnue est traitée comme un faux. Pas (inconnu) est inconnu

Dans l'exemple ci-dessous, je vais essayer de dire si un couple (a1, b1) est égal à (a2, b2). Notez que chaque colonne a 3 valeurs 0, 1 et NULL.

DECLARE @t table (a1 bit, a2 bit, b1 bit, b2 bit)

Insert into @t (a1 , a2, b1, b2) 
values( 0 , 0 , 0 , NULL )

select 
a1,a2,b1,b2,
case when (
    (a1=a2 or (a1 is null and a2 is null))
and (b1=b2 or (b1 is null and b2 is null))
)
then 
'Equal'
end,
case when not (
    (a1=a2 or (a1 is null and a2 is null))
and (b1=b2 or (b1 is null and b2 is null))
)
then 
'not Equal'
end,
case when (
    (a1<>a2 or (a1 is null and a2 is not null) or (a1 is not null and a2 is null))
or (b1<>b2 or (b1 is null and b2 is not null) or (b1 is not null and b2 is null))
)
then 
'Different'
end
from @t

Notez qu'ici nous attendons des résultats :

  • Egale à être nulle
  • pas égal à être pas égal
  • différent pour être différent

mais nous obtenons un autre résultat

  • Equal est nul OK
  • Non égal est nul ? ??
  • Différent, c'est différent

5voto

Tim Sullivan Points 10677

Il n'y aura pas d'impact sur les performances, les deux déclarations sont parfaitement égales.

HTH

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X