在 SQL 查询里,操作符主要用于运算、比较或逻辑组合,是 “工具性符号 / 词语”(如:+、=、AND),作用是处理数据或条件关系。简单说,操作符更像 “运算工具”,和我们一样,是 SQL 查询里的“隐形工具人”。加加减减靠算术操作符,筛选数据靠比较操作符,组合条件靠逻辑操作符。别看它们只是+、=、AND这些符号或词语,用对了我们能快速捞出想要的数据,用错了可能慢到花儿都谢了。下面我们把 47 个常用 SQL 操作符按场景拆解,不管是拼接字符串、处理空值,还是合并结果集,我们都能找到对应工具,就算咱们是新手也能一看就懂。
下面,我们先让 47 个常用 SQL 操作符一起露个脸,按照类别站队:
- 比较操作符:12个(
=
、<>
、!=
、<
、>
、<=
、>=
、BETWEEN ... AND ...
、IN
、NOT IN
、LIKE
、IS NULL
、IS NOT NULL
)
注:<>
和!=
功能一致,合计12个 - 字符串连接操作符:2个(
||
、CONCAT()
)
注:CONCAT()
函数形式按操作符逻辑计入 - 集合操作符:4个(
UNION
、UNION ALL
、INTERSECT
、EXCEPT
/MINUS
)
注:MINUS
为EXCEPT
的Oracle等价形式,合计4个 - 特殊比较操作符:3个(
IS TRUE
、IS FALSE
、IS DISTINCT FROM
) - 空值安全操作符:4个(
<=>
、COALESCE()
、??
、DIV
) - 类型转换操作符:1个(
::
)
注:其他数据库以函数形式实现,仅PostgreSQL的::
为操作符 - 正则表达式操作符:4个(
REGEXP
、RLIKE
、~
、~*
)
下面,我们接着一步步深入,对 47 个常用 SQL 操作符逐一简介:
1、算术操作符
用于数值计算,所有主流数据库(MySQL、PostgreSQL、Oracle、SQL Server、SQLite等)均支持:
/
:除法(如:a / b
,注意整数除法可能返回整数,如:5/2
在部分数据库返回2)%
:取模(返回除法余数,如:5 % 2
结果为1)
2、比较操作符
用于判断数据关系,所有主流数据库支持,核心功能一致:
- 基础比较:
=
(等于)、<>
或!=
(不等于)、<
(小于)、>
(大于)、<=
(小于等于)、>=
(大于等于) BETWEEN ... AND ...
:匹配指定范围(如:age BETWEEN 18 AND 30
等效于 age >=18 AND age <=30
)IN
:匹配列表中的任意值(如:status IN ('active', 'pending')
)
LIKE
:模糊匹配,%
代表任意长度字符(包括0个),_
代表单个字符(如:name LIKE '张%'
匹配“张三”、“张伟”)IS NULL
:判断值为NULL(不能用 = NULL
,NULL与任何值比较均为UNKNOWN)
3、逻辑操作符
用于组合条件判断,所有主流数据库支持:
AND
:逻辑与(所有条件均满足时为真,如:age >18 AND status = 'active'
)OR
:逻辑或(至少一个条件满足时为真,如:age <18 OR vip = 1
)NOT
:逻辑非(取反条件,如:NOT (age > 60)
等效于 age <=60
)
注:不同数据库(如:MySQL, PostgreSQL, SQL Server)对 !/&&/||
的支持有差异,建议优先使用标准关键词(NOT/AND/OR
)保证兼容性。XOR
运算符仅在部分数据库(如:MySQL)中直接支持。
4、位操作符(部分数据库支持)
对整数按二进制位进行运算,语法一致但支持范围有限:
&
:按位与(如:3 & 5
结果为1,二进制 011 & 101 = 001
)|
:按位或(如:3 | 5
结果为7,二进制 011 | 101 = 111
)^
:按位异或(如:3 ^ 5
结果为6,二进制 011 ^ 101 = 110
)~
:按位取反(如:~3
结果为-4,二进制补码取反)<< / >>
:位左移/右移(如:5 << 1 结果为10,二进制 0101 左移1位为 1010)。
注:支持MySQL、PostgreSQL、SQL Server。按位取反~的结果与数据库的整数存储方式(如是否支持无符号整数)相关,在 MySQL 中~3结果为-4(补码规则),但在 PostgreSQL 中若使用无符号整数类型,结果可能不同,因此该结果基于 MySQL 等使用补码存储整数的数据库,不同数据库可能因类型定义有差异。示例:SELECT ~CAST(3 AS UNSIGNED)
在MySQL返回超大数(无符号取反)。
5、字符串连接操作符(数据库差异明显)
用于拼接字符串,语法因数据库而异:
||
操作符:支持PostgreSQL、Oracle、SQLite,示例:'Hello' || 'World'
结果为:“HelloWorld”CONCAT()
函数:支持MySQL、SQL Server,示例:CONCAT('Hello', 'World')
结果为:“HelloWorld”
注:MySQL中+
不能用于字符串连接(会被当作数值相加),必须用CONCAT()
。在MySQL中,如果操作数均为字符串,+
会返回0
(因为无法转换为数值相加),因此必须使用CONCAT()
或CONCAT_WS()
进行字符串拼接。
示例:
-- MySQL中:'100' + 50 → 150(数值相加),'abc' + 50 → 50(非数字转0)
6、集合操作符(通用逻辑,语法/支持度差异)
用于合并多个查询的结果集(要求列数、类型一致):
UNION ALL
:合并结果并保留重复,所有主流数据库支持(效率高于UNION
)INTERSECT
:取两个结果集的交集(共有的行),注:支持Oracle、PostgreSQL、SQL Server;MySQL 8.0+支持EXCEPT
/MINUS
:取第一个结果集减去交集的差集,注:标准语法EXCEPT
支持PostgreSQL、SQL Server;Oracle用MINUS
;MySQL 8.0+支持EXCEPT
7、特殊比较操作符(特定场景/数据库)
解决常规比较的局限性(如:NULL值判断):
IS TRUE
/ IS FALSE
:判断布尔值(如:active IS TRUE
),所有数据库通用。IS DISTINCT FROM
:严格比较(含NULL值),解决a <> b
在a
或b
为NULL时返回UNKNOWN的问题:- 示例:
a IS DISTINCT FROM b
→ 当a
和b
均为NULL时返回FALSE
(而a <> b
返回UNKNOWN)。IS DISTINCT FROM
在PostgreSQL中非常实用,因为它能正确处理NULL值的比较,而其他数据库(如:MySQL、Oracle)需要手动处理NULL值逻辑。 - 注:支持PostgreSQL、SQLite;不支持MySQL、Oracle、SQL Server(需用
(a <> b OR a IS NULL <> b IS NULL)
替代)。
8、JSON操作符(现代数据库支持)
用于查询JSON类型字段(需数据库支持JSON类型):
->
:获取JSON字段(返回JSON类型),注:MySQL 5.7+、PostgreSQL 9.3+支持。Oracle 12c+也支持JSON操作符,但语法略有不同(如:JSON_VALUE、JSON_QUERY等函数)。->>
:获取JSON字段(返回字符串类型),注:MySQL 5.7+、PostgreSQL 9.3+支持#>
:按路径获取JSON字段,注:PostgreSQL专有(如:data #> '{user, name}'
)
示例:若data
为JSON字段{"user": {"name": "张三"}}
,则:
data->'user'
返回 {"name": "张三"}
(JSON类型);data->'user'->>'name'
返回 '张三'
(字符串类型)。
9、空值安全操作符(处理NULL值的特殊场景)
解决NULL
值比较的歧义(NULL与任何值运算/比较均为NULL):
<=>
:空值安全等于(NULL=NULL返回TRUE),注:MySQL专有(如:a <=> b
,替代a = b
且支持NULL比较)。SQL Server和Oracle没有直接的<=>操作符,但可以通过COALESCE或NULLIF实现类似功能(如:NULLIF(COALESCE(a, b), NULL)
)。COALESCE()
:返回参数列表中第一个非NULL值,所有数据库通用(如:COALESCE(a, b, 0)
→ 若a为NULL则取b,b也为NULL则取0)??
:空值合并(等效COALESCE(a, b)
),注:SQLite专有(如:a ?? b
→ 若a为NULL则返回b)DIV
:整数除法,忽略NULL(如:a DIV b,若 b 为NULL,结果为0)。注:仅MySQL支持。
10、类型转换操作符(数据库差异)
隐式转换数据类型:
::
:PostgreSQL的隐式转换语法(如:'123'::INT)。
注:仅PostgreSQL支持。其他数据库的类型转换方式:
MySQL:CAST('123' AS SIGNED)
SQL Server:CAST('123' AS INT)
Oracle:TO_NUMBER('123')
11、正则表达式操作符(部分数据库支持)
用于复杂模式匹配:
REGEXP / RLIKE
:正则匹配(如:name REGEXP '^张'
匹配所有姓“张”的人)。~ / ~*
:PostgreSQL的正则操作符(~区分大小写,~*不区分)。
注:REGEXP
:MySQL、SQL Server支持;Oracle用 REGEXP_LIKE()
函数。RLIKE
:MySQL别名,功能同 REGEXP
。~ / ~*
:PostgreSQL专有。SQLite 3.9.0+也支持正则表达式,但需要通过REGEXP
函数实现(通常需要自定义正则表达式函数)。
说明:
(1)未特别标注的操作符,均符合SQL标准,支持主流数据库(MySQL、PostgreSQL、Oracle、SQL Server、SQLite)。
(2)实际使用需注意数据库版本(如:MySQL 8.0新增较多功能,低版本可能不支持)。
以下,我们进入正题,再对 SQL 操作符进行深度拆解,从基础应用到高阶应用,仅供参考:
一、常用 SQL 操作符的基础应用
1、算术操作符(数值计算核心)
+
(加法/拼接)
-- 数值加法
SELECT price + tax FROM orders;
-- 字符串拼接(Oracle用 ||,MySQL/PostgreSQL 支持 || 或 CONCAT)
SELECT first_name + ' ' + last_name FROM users; -- SQL Server 语法
差异:Oracle 只能用 ||
拼接字符串,+
仅做加法。
-
(减法)
SELECT salary - 1000 AS net_salary FROM employees;
*
(乘法)
SELECT quantity * unit_price AS total FROM order_details;
/
(除法)
SELECT total_sales / 12 AS monthly_avg FROM reports;
注意:5/2
在 SQLite 中返回 2
(整数截断),在 PostgreSQL 中返回 2.5
(精确除)。多数数据库整数除法会截断小数部分。
%
(取模/余数)
SELECT 9 % 4; -- MySQL/PostgreSQL 返回 1
SELECT MOD(9,4) FROM dual; -- Oracle 语法
2、比较操作符(条件过滤基础)
=
/ <>
(等于/不等于)
SELECT * FROM users WHERE status = 'active';
SELECT * FROM products WHERE category_id <> 5; -- 标准语法
注意:!=
是非标准操作符,部分数据库(如:Oracle)可能不支持。
>
/ <
/ >=
/ <=
(大小比较)
SELECT name FROM students WHERE age >= 18;
BETWEEN
(闭区间范围)
SELECT * FROM orders
WHERE order_date BETWEEN '2024-01-01' AND '2024-12-31';
-- 等价于 order_date >= '2024-01-01' AND order_date <= '2024-12-31'
IN
/ NOT IN
(集合匹配)
SELECT * FROM employees WHERE id IN (101, 205, 309);
SELECT * FROM customers WHERE country NOT IN ('US','JP');
陷阱:NOT IN
列表含 NULL
时条件永不为真(如:country NOT IN ('US', NULL)
)。
LIKE
(模糊匹配)
SELECT title FROM books WHERE title LIKE 'SQL%'; -- 以SQL开头
SELECT phone FROM contacts WHERE phone LIKE '1__-___-____'; -- 1开头的11位号码
转义:ESCAPE
可定义通配符转义(如:LIKE '100#%' ESCAPE '#'
匹配 100%
)。
IS NULL
(空值判断)
SELECT * FROM orders WHERE discount_code IS NULL; -- 正确写法
-- WHERE discount_code = NULL 错误!始终返回空结果集
3、逻辑操作符(条件组合逻辑)
AND
(逻辑与)
SELECT * FROM staff
WHERE department = 'Sales' AND salary > 5000; -- 必须同时成立
OR
(逻辑或)
SELECT * FROM flights
WHERE departure_city = 'Shanghai' OR arrival_city = 'Shanghai';
NOT
(逻辑非)
SELECT * FROM users WHERE NOT is_deleted; -- 排除已删除用户
特殊操作符(子查询关联)
-- EXISTS: 子查询是否返回记录
SELECT * FROM departments d
WHERE EXISTS (SELECT 1 FROM employees e WHERE e.dept_id = d.id);
-- IN 的等效写法
SELECT * FROM products
WHERE category_id IN (SELECT id FROM categories WHERE is_active = 1);
4、位操作符(特定场景使用)
-- 权限系统示例(假设 flags 是整数位掩码)
SELECT user_id FROM permissions
WHERE flags & 4 = 4; -- 检查第3位是否开启(读权限)
二、常用 SQL 操作符的优先级
1、优先级顺序(从高到低)
()
> 算术运算(*,/,%)
> 算术运算(+,-)
> 比较操作符(=,>,<...)
> NOT
> AND
> OR
2、优先级金字塔(从高到低)
1. 括号 ()
2. 算术运算符: * / %
3. 算术运算符: + -(正负号)
4. 算术运算符: + -(加减)
5. 位运算符: ~(按位取反)
6. 位运算符: &(按位与)
7. 位运算符: ^(按位异或)
8. 位运算符: |(按位或)
9. 比较运算符: =, >, <, >=, <=, <>, BETWEEN, LIKE, IN, IS NULL
10.逻辑非: NOT
11.逻辑与: AND
12.逻辑或: OR
示例1
SELECT * FROM employees
WHERE salary > 5000 OR department = 'HR' AND hire_date < '2020-01-01';
实际逻辑:salary > 5000
OR (department = 'HR'
AND hire_date < '2020-01-01'
)
因 AND
优先级高于 OR
。若需逻辑或优先,必须加括号:
WHERE (salary > 5000 OR department = 'HR') AND hire_date < '2020-01-01';
示例2
SELECT * FROM products
WHERE (category_id = 5 OR discount > 20)
AND NOT is_discontinued
AND price * 0.8 < 100;
执行顺序:
(category_id = 5 OR discount > 20)
(括号优先)
3、跨数据库优先级差异
算术操作符优先级基本一致(* / %
> + -
),但取模操作符 %
在部分数据库(如:SQL Server)中与 * /
优先级相同,建议用括号明确:
SELECT 10 * 5 % 3; -- 结果可能是 (10*5)%3=50%3=2,或 10*(5%3)=10*2=20
-- 安全写法:
SELECT (10 * 5) % 3;
三、操作符 vs 关键字的重合边界
SQL 关键字是用于定义 SQL 语句结构的保留词,如:SELECT、FROM、WHERE 等。SQL 操作符用于比较和逻辑运算,如:=、>、AND、OR。关键字和操作符共同构成 SQL 查询的基础,用于数据检索、过滤和操作。
1、对比示例
-- 示例1
-- 操作符主导表达式
SELECT (unit_price * quantity) * (1 - discount) AS net_total -- 算术操作符
FROM order_details
WHERE status IN ('shipped','delivered') OR is_priority = 1; -- 比较+逻辑操作符
-- 关键字定义语句框架
UPDATE products
SET stock = stock - 10 -- SET 关键字引导赋值
WHERE id = 100; -- WHERE 关键字引导条件
-- 示例2
-- 操作符主导的表达式(产生新值)
SELECT
unit_price * quantity * (1 - discount) AS net_total, -- 算术操作符
CASE WHEN quantity > 100 THEN 1 ELSE 0 END AS bulk_flag -- CASE内部操作符
FROM orders;
-- 关键字控制的语句结构(无返回值)
SELECT product_name -- SELECT子句
FROM inventory -- FROM子句
WHERE stock_count > 0 -- WHERE子句
ORDER BY last_restock_date; -- ORDER BY子句
2、特殊元素的双重身份
- 操作符属性:在表达式中进行值比较
WHERE price BETWEEN 10 AND 20; -- 比较操作
- 关键字形态:语法结构接近子句(后跟范围值,需要AND连接范围)
- 内部
WHEN
, THEN
为逻辑操作符:SELECT
CASE -- 关键字(控制流)
WHEN score >= 90 THEN 'A' -- WHEN 逻辑比较操作符
WHEN score >= 80 THEN 'B' -- THEN 赋值操作符
ELSE 'C' -- ELSE操作符(默认赋值)
END AS grade
3、区分原则
操作符处理数据单元间关系(如:price * quantity
)。
关键字指挥数据库如何操作数据(如:GROUP BY
, ORDER BY
, JOIN
)。
二者如同句子中的"动词"和"连接词",共同构建完整的SQL语义。
四、常用 SQL 操作符的进阶应用
1、算术操作符:数值计算核心
(1)加法(+)与拼接陷阱
-- 数值加法(通用)
SELECT unit_price + shipping_fee AS total_cost FROM orders;
-- 字符串拼接(数据库差异)
/* SQL Server */ SELECT first_name + ' ' + last_name AS full_name FROM employees;
/* MySQL/Oracle */ SELECT CONCAT(first_name, ' ', last_name) AS full_name;
/* PostgreSQL */ SELECT first_name || ' ' || last_name AS full_name;
注意:SQL Server中'100' + 50
返回150
(隐式转换),MySQL返回'10050'
(字符串拼接)
(2)除法精度问题实战
-- 整数截断(MySQL/SQL Server)
SELECT 5/2; -- 返回2
-- 精确计算解决方案
SELECT 5.0/2; -- 返回2.5(SQL Server)
SELECT CAST(5 AS FLOAT)/2; -- 通用方案
SELECT 5/2.0; -- PostgreSQL/MySQL返回2.5
(3)取模运算的跨库方案
-- 通用写法(使用函数)
SELECT MOD(17,5); -- 所有数据库支持函数形式
-- 操作符方案
SELECT 17 % 5; -- MySQL/PostgreSQL/SQL Server支持
2、比较操作符:数据过滤基石
(1)BETWEEN的日期边界陷阱
-- 错误示例(包含2023-12-31 23:59:59)
SELECT * FROM orders
WHERE order_date BETWEEN '2023-01-01' AND '2023-12-31';
-- 正确方案
SELECT * FROM orders
WHERE order_date >= '2023-01-01'
AND order_date < '2024-01-01'; -- 确保不包含次年
(2)NOT IN的NULL灾难
-- 危险查询(当subquery包含NULL时永远返回空)
SELECT * FROM products
WHERE category_id NOT IN (
SELECT category_id FROM discontinued_categories -- 此子查询可能返回NULL
);
-- 安全替代方案
SELECT * FROM products p
WHERE NOT EXISTS (
SELECT 1 FROM discontinued_categories d
WHERE d.category_id = p.category_id
);
(3)LIKE通配符高级用法
-- 匹配带百分号的文件名
SELECT * FROM documents
WHERE filename LIKE 'report\_2023%.pdf' ESCAPE '\';
-- 手机号模糊匹配
SELECT * FROM users
WHERE phone LIKE '138________'; -- 138开头+8位数字
3、逻辑操作符:组合条件艺术
(1)AND/OR优先级陷阱
-- 错误逻辑(先计算AND)
SELECT * FROM employees
WHERE department = 'IT' OR department = 'HR' AND salary > 8000;
/* 等价于:IT部门全部员工 或 HR部门且薪资>8000的员工 */
-- 正确加括号方案
SELECT * FROM employees
WHERE (department = 'IT' OR department = 'HR')
AND salary > 8000; -- 两个部门中高薪员工
(2)EXISTS性能优化实战
-- 低效IN写法
SELECT * FROM customers
WHERE id IN (SELECT customer_id FROM large_orders_table);
-- 高效EXISTS写法
SELECT * FROM customers c
WHERE EXISTS (
SELECT 1 FROM large_orders_table o
WHERE o.customer_id = c.id
LIMIT 1 -- 找到第一条即停止
);
4、位操作符:状态管理利器
-- 权限系统实战(权限位:1=读,2=写,4=执行)
/* 检查读写权限 */
SELECT user_id FROM permissions
WHERE (access_flags & 3) = 3; -- 同时具备1和2位
/* 添加执行权限 */
UPDATE permissions
SET access_flags = access_flags | 4
WHERE user_id = 1001;
/* 移除写权限 */
UPDATE permissions
SET access_flags = access_flags & ~2
WHERE user_id = 1002;
五、跨数据库操作符差异解决方案
| | |
---|
字符串拼接 | CONCAT(str1, str2) | MySQL:CONCAT() 必需 Oracle:只能用` |
空值安全等于 | a IS NOT DISTINCT FROM b | MySQL:a <=> b Oracle:需用NVL(a,-1)=NVL(b,-1) |
取模运算 | MOD(dividend, divisor) | |
正则匹配 | REGEXP_LIKE(str, pattern) | MySQL:REGEXP PostgreSQL:~ SQLite:需扩展支持 |
整数除法 | CAST(a AS FLOAT)/b | MySQL:DIV 返回整数 SQL Server:a/b 自动取整 |
六、常用 SQL 操作符的高阶应用
1、NULL安全处理三原则
-- 危险:与NULL比较永远返回未知
SELECT * FROM users WHERE phone = NULL; -- 错误!
-- 方案1:显式NULL检查
SELECT * FROM orders WHERE coupon_code IS NULL;
-- 方案2:COALESCE转换
SELECT * FROM products
WHERE COALESCE(discount, 0) > 10; -- NULL视为0
-- 方案3:NULLIF避免除零错误
SELECT revenue / NULLIF(order_count, 0) AS avg_revenue;
2、性能优化四准则
-- 准则1:用UNION ALL替代OR(索引优化)
SELECT * FROM log WHERE type = 'login'
UNION ALL
SELECT * FROM log WHERE type = 'logout';
-- 准则2:避免函数包装索引列
/* 低效 */ SELECT * FROM users WHERE YEAR(created_at) = 2023;
/* 高效 */ SELECT * FROM users WHERE created_at >= '2023-01-01' AND created_at < '2024-01-01';
-- 准则3:LIKE左通配优化
/* 无法用索引 */ SELECT * FROM products WHERE name LIKE '%pro%';
/* 可用索引 */ SELECT * FROM products WHERE name LIKE 'pro%';
-- 准则4:批量更新避坑
UPDATE orders SET status = 'processed' WHERE id IN (1,3,5...500); -- IN列表过长
/* 改用临时表 */
CREATE TEMP TABLE ids_to_update(id INT PRIMARY KEY);
INSERT INTO ids_to_update VALUES (1),(3),...(500);
UPDATE orders o JOIN ids_to_update t ON o.id = t.id
SET o.status = 'processed';
3、类型转换防御策略
-- 隐式转换风险示例
SELECT * FROM transactions WHERE trx_id = '10012'; -- 字符串转数字
-- 防御方案1:严格匹配类型
SELECT * FROM transactions WHERE trx_id = 10012;
-- 防御方案2:显式转换
SELECT * FROM user_actions
WHERE CAST(action_time AS DATE) = '2023-06-01'; -- 可控转换
4、动态定价算法
SELECT product_id,
base_price *
CASE
WHEN inventory_level < 10 THEN 1.2 -- 低库存溢价
WHEN DATEDIFF(now(), release_date) > 365 THEN 0.8 -- 旧款折扣
ELSE 1.0
END *
(1 - COALESCE(member_discount, 0)) AS dynamic_price
FROM products
WHERE is_active = 1;
5、多层级权限校验
SELECT u.user_id,
MAX(CASE WHEN p.access_flags & 1 = 1 THEN 1 ELSE 0 END) AS can_read,
MAX(CASE WHEN p.access_flags & 2 = 2 THEN 1 ELSE 0 END) AS can_write
FROM users u
LEFT JOIN permission_groups pg ON u.group_id = pg.id
LEFT JOIN global_permissions p ON pg.permission_mask & p.mask > 0
GROUP BY u.user_id;
总结:SQL 操作符实践指南
- 始终用
IS NULL/IS NOT NULL
处理空值
学会这 47 个 SQL 操作符,我们手里就有了一套 “万能扳手”,算数值用算术操作符,筛数据用比较操作符,拼条件用逻辑操作符,遇到特殊场景还有 JSON、位操作符兜底。我们只要“按需选工具”,复杂查询加括号明确优先级,跨数据库稳妥采用通用语法,按场景挑对操作符,下次我们写 SQL 时,就不会再对着符号犯愁了,查询效率和准确性自然能提上来。
该文章在 2025/8/5 16:28:08 编辑过