During parsing, SQL Server calls sqllang!DecodeCompOp
to determine the type of comparison operator present:
This occurs well before anything in the optimizer gets involved.
From Comparison Operators (Transact-SQL)
Tracing the code using a debugger and public symbols*, sqllang!DecodeCompOp
returns a value in register eax
** as follows:
╔════╦══════╗
║ Op ║ Code ║
╠════╬══════╣
║ < ║ 1 ║
║ = ║ 2 ║
║ <= ║ 3 ║
║ !> ║ 3 ║
║ > ║ 4 ║
║ <> ║ 5 ║
║ != ║ 5 ║
║ >= ║ 6 ║
║ !< ║ 6 ║
╚════╩══════╝
!=
and <>
both return 5, so are indistinguishable in all later operations (including compilation & optimization).
Though secondary to the above point, it is also possible (e.g. using undocumented trace flag 8605) to look at the logical tree passed to the optimizer to confirm that both !=
and <>
map to ScaOp_Comp x_cmpNe
(not equal scalar operator comparison).
For example:
SELECT P.ProductID FROM Production.Product AS P
WHERE P.ProductID != 4
OPTION (QUERYTRACEON 3604, QUERYTRACEON 8605);
SELECT P.ProductID FROM Production.Product AS P
WHERE P.ProductID <> 4
OPTION (QUERYTRACEON 3604, QUERYTRACEON 8605);
both produce:
LogOp_Project QCOL: [P].ProductID
LogOp_Select
LogOp_Get TBL: Production.Product(alias TBL: P)
ScaOp_Comp x_cmpNe
ScaOp_Identifier QCOL: [P].ProductID
ScaOp_Const TI(int,ML=4) XVAR(int,Not Owned,Value=4)
AncOp_PrjList
Footnotes
* I use WinDbg; other debuggers are available. Public symbols are available via the usual Microsoft symbol server. For more information, see Looking deeper into SQL Server using Minidumps by the SQL Server Customer Advisory Team and SQL Server Debugging with WinDbg – an Introduction by Klaus Aschenbrenner.
** Using EAX on 32-bit Intel derivatives for return values from a function is common. Certainly the Win32 ABI does it that way, and I'm pretty sure it inherits that practice from back in the old MS-DOS days, where AX was used for the same purpose - Michael Kjörling