我正在努力解决SQL Server中的NULL值处理问题(在版本12.0.5000.0上测试)。基本上,我的目的是获得具有列值<>的所有行。静态值(例如999)。我没有搜索替代LIKE"使用ISNULL功能"。查询由第三方引擎生成,我不打算编写解析器并更改语句。
-- All examples with ANSI_NULLS OFF
SET ANSI_NULLS OFF;
GO
--------------------------------------------------------------------------------------------------------
-- "Virtual" example / working as expected
--------------------------------------------------------------------------------------------------------
DECLARE
@One INT = 1,
@Null INT = NULL
SELECT
IIF(@Null = NULL, 1, 0) '@Null = NULL' -- To test if ANSI_NULL is OFF
,IIF(@One <> NULL, 1, 0) '@One <> NULL' -- working with NULL variable
,IIF(1 <> NULL, 1, 0) '1 <> NULL' -- working with NULL value
--------------------------------------------------------------------------------------------------------
-- MSDN Example / NOT working as expected
-- https://docs.microsoft.com/en-us/sql/t-sql/statements/set-ansi-nulls-transact-sql
--------------------------------------------------------------------------------------------------------
-- Create table t1 and insert values.
CREATE TABLE dbo.t1 (a INT NULL);
INSERT INTO dbo.t1 values (NULL),(0),(1);
GO
-- SET ANSI_NULLS to OFF and test.
DECLARE @varname int;
SET @varname = 999;
SELECT a
FROM t1
WHERE a <> @varname; -- working with NULL variable
SELECT a
FROM t1
WHERE a <> 999; -- NOT working with NULL value
-- Drop table t1.
DROP TABLE dbo.t1;
任何人都可以解释为什么&#34;虚拟&#34;示例是以与MSDN示例不同的方式工作吗?
Virtual example:
+--------------+--------------+-----------+
| @Null = NULL | @One <> NULL | 1 <> NULL |
+--------------+--------------+-----------+
| 1 | 1 | 1 |
+--------------+--------------+-----------+
MSDN example:
-- SELECT 1
+------+
| a |
+------+
| NULL |
| 0 |
| 1 |
+------+
-- SELECT 2
+------+
| a |
+------+
| 0 |
| 1 |
+------+
答案 0 :(得分:2)
看起来查询优化器会选择不同的比较运算符:
DECLARE @varname int;
SET @varname = 999;
SELECT a
FROM t1
WHERE a <> @varname;
XML执行计划:
<Predicate>
<ScalarOperator ScalarString="[fiddle_84f7799901e54a779e8bff464a2d01f3].[dbo].[t1].[a] <> [@varname]">
<Compare CompareOp="IS NOT">
<ScalarOperator>
<Identifier>
<ColumnReference Database="[fiddle_84f7799901e54a779e8bff464a2d01f3]" Schema="[dbo]" Table="[t1]" Column="a"></ColumnReference>
</Identifier>
</ScalarOperator>
<ScalarOperator>
<Identifier>
<ColumnReference Column="@varname"></ColumnReference>
</Identifier>
</ScalarOperator>
</Compare>
</ScalarOperator>
</Predicate>
比较CompareOp = “不是”
使用硬编码值的第二个查询:
SELECT a
FROM t1
WHERE a <> 999;
-- same as
DECLARE @varname int = 999;
SELECT a
FROM t1
WHERE a <> (SELECT @varname);
XML执行计划:
<Predicate>
<ScalarOperator ScalarString="[fiddle_ac5121a789da473382366733b51ef441].[dbo].[t1].[a]<>(999)">
<Compare CompareOp="NE">
<ScalarOperator>
<Identifier>
<ColumnReference Database="[fiddle_ac5121a789da473382366733b51ef441]" Schema="[dbo]" Table="[t1]" Column="a"></ColumnReference>
</Identifier>
</ScalarOperator>
<ScalarOperator>
<Const ConstValue="(999)"></Const>
</ScalarOperator>
</Compare>
</ScalarOperator>
</Predicate>
比较CompareOp = “NE”
修改强>
<强> SET ANSI_NULLS 强>
SET ANSI_NULLS ON仅在比较的其中一个操作数是NULL或文字NULL的变量时才会影响比较。 如果比较的两边都是列或复合表达式,则该设置不会影响比较。