数据库 NULL 值对比运算符(null safe equal)

在 SQL 的规定中,NULL 是不等于 NULL 的,所以如果使用类似 SELECT NULL = NULL 这种语句,获取到的会是一个 FALSE。

但是有些时候我们又希望能够匹配到数据库中的 NULL,通常写法是 SELECT NULL IS NULL,但是有没有能够同时兼容 NULL 和非 NULL 的情况呢?

MySQL

MySQL :: MySQL 5.7 Reference Manual :: 12.4.2 Comparison Functions and Operators

mysql> SELECT 1 <=> 1, NULL <=> NULL, 1 <=> NULL;
        -> 1, 1, 0
mysql> SELECT 1 = 1, NULL = NULL, 1 = NULL;
        -> 1, NULL, NULL

Oracle

Comparing NULLable Values | An Oracle Programmer

Oracle Null Safe Comparison (Spoiler alert: SYS_OP_MAP_NONNULL) | Aykut Akın’s Blog

PostgreSQL

a IS DISTINCT FROM b
a IS NOT DISTINCT FROM b

PostgreSQL: Documentation: 9.2: Comparison Operators

PostgreSQL: Re: NULL safe equality operator

SQL Server

SQL Server 没有这种操作符,只能通过控制 ANSI_NULLS 来控制,但是这个只影响列和常量比较,不影响两个列之间的比较,所以还是有缺陷。

Changing the setting of ANSINULLS is not a solution, because it does not affect column-to-column comparisons, only column to variable comparisons. Setting ANSINULLS to off is also non-standard and not granular enough to apply to specific comparisons in a single query.

——Add language and optimizer support for ISO – Customer Feedback for ACE Community Tooling

一种通用的写法:

或者可以写成 (b IS NULL AND b IS NULL) OR (a IS NOT NULL AND b IS NOT NULL AND a = b)

Does SQL Server support IS DISTINCT FROM clause? - Stack Overflow

sql - How to rewrite IS DISTINCT FROM and IS NOT DISTINCT FROM? - Stack Overflow

= (Equals) (Transact-SQL) - SQL Server | Microsoft Docs

SET ANSI_NULLS (Transact-SQL) - SQL Server | Microsoft Docs

Mimicking null-safe equal to operator in SQL Server - CodeProject

Why does NULL = NULL evaluate to false in SQL server - Stack Overflow

参考资料

  1. Modern SQL: IS DISTINCT FROM — A comparison operator that treats two NULL values as the same
  2. Comparing NULLable Values | An Oracle Programmer
<think>好的,用户现在在问SQL中比较两个大小的函数。根据之前的对话,用户已经了解了一些基础方法,比如关系运算符和CASE语句,现在可能想更深入地了解是否有专门的函数来完成这个任务。首先,我需要回忆一下SQL中的比较函数。根据引用[2],提到了MySQL中的比较函数,比如处理NULL运算符。比如,<=>运算符可以在两边都为NULL时返回true,而普通的=运算符在遇到NULL时会返回NULL。这可能是一个关键点,但用户可能更想知道如何比较两个的大小,而不仅仅是相等性。然后引用[4]中提到了SQLServer的自定义函数,用于比较四个的绝对并取最大。虽然这个例子是取最大,但用户的问题是关于比较两个的大小,可能需要类似GREATEST或LEAST函数的信息。不过,不同数据库的支持情况不同,比如MySQL有GREATEST和LEAST,而SQL Server可能需要用CASE语句或者自定义函数实现。 此外,用户之前的回答提到了使用关系运算符和CASE语句,所以现在需要补充是否有内置函数可以直接比较两个的大小。例如,SIGN函数可以返回数的符号,可能用于比较结果,但可能不算直接的比较函数。还要注意不同数据库的差异,比如MySQL支持GREATEST,而SQLServer可能需要用户自定义函数,如引用[4]中的例子。需要指出这些差异,并提供相应的示例。 另外,用户可能混淆了比较运算符和函数,需要明确说明哪些是函数,哪些是运算符。例如,<=>在MySQL中是运算符,而不是函数,但可能被用户视为函数。最后,确保回答结构清晰,分点说明,并给出示例代码,同时处理NULL的情况,如引用[2]和[3]提到的聚集函数忽略NULL的情况,但比较时需要显式处理NULL。总结,需要涵盖以下几点: 1.直接比较运算符(如>、<、=)和CASE语句。 2.处理NULL的特殊运算符(如MySQL的<=>)。3.GREATEST/LEAST函数在不同数据库中的支持情况。4.使用SIGN函数辅助比较。 5.自定义函数的例子(如引用[4]中的SQL Server函数)。6.不同数据库的差异和注意事项。7.相关问题的生成,如处理NULL、日期比较、性能优化等。</think>### SQL 中比较两个大小的函数及方法 在 SQL 中,**没有直接用于比较两个大小的独立函数**(如 `compare(a, b)`),但可以通过 **关系运算符**、**条件表达式** 或 **特定数据库支持的函数** 实现。以下是具体方法及示例: --- ### 一、使用关系运算符直接比较 通过 `>`、`<`、`=` 等运算符直接比较两个: ```sql SELECT CASE WHEN a > b THEN 'a 大于 b' WHEN a < b THEN 'a 小于 b' ELSE 'a 等于或存在 NULL ' END AS result FROM table_name; ``` **适用场景**:数、日期、字符串等可比较类型[^1][^3]。 --- ### 二、处理 NULL 的比较函数 #### 1. MySQL 的 `<=>` 运算符NULL-safe 比较) 当比较的字段可能为 `NULL` 时,使用 `<=>` 可避免逻辑错误: ```sql -- 比较两个字段是否相等(包括 NULL) SELECT a <=> b AS is_equal FROM table_name; ``` **结果**: - 若 `a` 和 `b` 均为 `NULL`,返回 `1`(相等)[^2]; - 若仅一方为 `NULL`,返回 `0`(不相等)。 #### 2. 显式处理 NULL ```sql SELECT CASE WHEN a IS NULL OR b IS NULL THEN '存在 NULL ' WHEN a > b THEN 'a 大于 b' ELSE 'a 不大于 b' END FROM table_name; ``` --- ### 三、特定数据库的比较函数 #### 1. `GREATEST()` 和 `LEAST()`(MySQLPostgreSQL 支持) 比较多个并返回最大/最小: ```sql -- 比较两个的大小 SELECT GREATEST(a, b) AS max_value, LEAST(a, b) AS min_value FROM table_name; ``` **注意**:若参数包含 `NULL`,结果可能为 `NULL`[^3]。 #### 2. 自定义比较函数(以 SQL Server 为例) 若需比较绝对大小,可创建自定义函数: ```sql CREATE FUNCTION dbo.CompareAbs (@a FLOAT, @b FLOAT) RETURNS VARCHAR(10) AS BEGIN RETURN CASE WHEN ABS(@a) > ABS(@b) THEN 'a 绝对更大' WHEN ABS(@a) < ABS(@b) THEN 'b 绝对更大' ELSE '绝对相等或存在 NULL' END END; ``` 调用示例: ```sql SELECT dbo.CompareAbs(10, -15) AS result; -- 返回 "b 绝对更大"[^4] ``` --- ### 四、辅助函数:`SIGN()` 通过 `SIGN()` 获取数符号辅助比较: ```sql SELECT CASE SIGN(a - b) WHEN 1 THEN 'a 大于 b' WHEN -1 THEN 'a 小于 b' ELSE 'a 等于 b 或存在 NULL' END AS result FROM table_name; ``` **适用场景**:数类型比较。 --- ### 五、不同数据库的差异 | 数据库 | 支持函数/运算符 | 备注 | |--------------|-------------------------------|---------------------------| | **MySQL** | `<=>`, `GREATEST()`, `LEAST()` | 字符串比较区分大小写 | | **SQL Server**| 自定义函数(如引用[4]示例) | 需手动处理 NULL | | **PostgreSQL**| `GREATEST()`, `LEAST()` | 支持多参数比较 | --- ### 六、性能建议 1. **避免隐式类型转换** 确保比较字段类型一致,例如: ```sql SELECT * FROM table_name WHERE CAST(string_col AS INT) > 100; ``` 2. **索引优化** 对高频比较字段(如日期、数列)建立索引。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值