SELECT foreignStockId
FROM [Subset].[dbo].[Products]
Renvoie probablement un NULL .
Un NOT IN la requête ne renverra aucune ligne s'il y en a NULL s existe dans la liste des NOT IN valeurs. Vous pouvez les exclure explicitement en utilisant IS NOT NULL comme ci-dessous.
SELECT stock.IdStock,
stock.Descr
FROM [Inventory].[dbo].[Stock] stock
WHERE stock.IdStock NOT IN (SELECT foreignStockId
FROM [Subset].[dbo].[Products]
WHERE foreignStockId IS NOT NULL)
Ou réécrivez en utilisant NOT EXISTS à la place.
SELECT stock.idstock,
stock.descr
FROM [Inventory].[dbo].[Stock] stock
WHERE NOT EXISTS (SELECT *
FROM [Subset].[dbo].[Products] p
WHERE p.foreignstockid = stock.idstock)
En plus d'avoir la sémantique que vous souhaitez, le plan d'exécution pour NOT EXISTS est souvent plus simple comme on le voit ici.
La raison de la différence de comportement est due à la logique à trois valeurs utilisée dans SQL. Les prédicats peuvent être évalués à True , False , ou Unknown .
Un WHERE la clause doit être évaluée à True pour que la ligne soit retournée mais ce n'est pas possible avec NOT IN quand NULL est présent comme expliqué ci-dessous.
'A' NOT IN ('X','Y',NULL) est équivalent à 'A' <> 'X' AND 'A' <> 'Y' AND 'A' <> NULL)
- 'A' <> 'X' =
True - 'A' <> 'O' =
True - 'A' <> NULL =
Unknown
True AND True AND Unknown est évalué à Unknown selon les tables de vérité pour la logique à trois valeurs.
Les liens suivants contiennent des informations supplémentaires sur les performances des différentes options.
- Dois-je utiliser
NOT IN,OUTER APPLY,LEFT OUTER JOIN,EXCEPT, ouNOT EXISTS? NOT INvsNOT EXISTSvsLEFT JOIN / IS NULL:SQL ServerLeft outer joinvsNOT EXISTSNOT EXISTSvsNOT IN