PostgreSQL 运算符
运算符(Operators)是 PostgreSQL 中的特殊符号或关键字,用于对一个或多个值(称为操作数)执行操作并生成结果。
在构建过滤、操作和组合数据库中数据的表达式和查询时,运算符是不可或缺的基础工具。它们允许你定义条件、执行计算以及比较数值,从而让你的 SQL 查询变得动态且强大。
PostgreSQL 支持多种类别的运算符,每种都针对特定类型的操作而设计。
1. 算术运算符 (Arithmetic Operators)
算术运算符用于对数值执行数学计算,包括加、减、乘、除和取模操作。
- 加法 (
+): 将两个操作数相加。 - 示例:
SELECT 10 + 5;结果为15。 - 实际业务场景: 计算订单中所有商品的总价。如果客户买了一件 25 美元的衬衫和一条 40 美元的裤子,总成本就是
25 + 40 = 65。 - 假设场景: 物流公司计算两个包裹的总重量。A 包裹重 15.5 kg,B 包裹重 7.2 kg,运费计算的总重量为
15.5 + 7.2 = 22.7kg。 - 减法 (
-): 从第一个操作数中减去第二个操作数。 - 示例:
SELECT 10 - 5;结果为5。 - 实际业务场景: 通过从收入中减去销货成本来确定利润率。如果产品售价 100 美元,生产成本 30 美元,利润就是
100 - 30 = 70。 - 假设场景: 学校计算购买学习用品后的剩余预算。初始预算是 5000 美元,买教材花了 1200 美元,剩余预算为
5000 - 1200 = 3800。 - 乘法 (
*): 将两个操作数相乘。 - 示例:
SELECT 10 * 5;结果为50。 - 实际业务场景: 计算多件同款商品的总价。单价 12 美元,客户买了 3 件,总价为
12 * 3 = 36。 - 假设场景: 投资公司预测投资的未来价值。如果 10,000 美元的初始投资每年增长 1.05 倍,一年后的价值为
10000 * 1.05 = 10500。 - 除法 (
/): 第一个操作数除以第二个操作数。 - 示例:
SELECT 10 / 5;结果为2。注意: 整数除法会截断小数部分。要进行浮点除法,请确保至少有一个操作数是浮点数(例如,10.0 / 3)。 - 实际业务场景: 计算学生的平均分。如果 5 名学生的总分是 450 分,平均分就是 450 / 5 = 90。
- 假设场景: 工厂确定一定量的原材料可以生产多少批产品。如果有 1500 kg 材料,每批需要 250 kg,可生产的批次为
1500 / 250 = 6。 - 取模 (
%): 返回除法运算后的余数。 - 示例:
SELECT 10 % 3;结果为1。 - 实际业务场景: 判断一个数字是奇数还是偶数(如果 数字
% 2 = 0则是偶数)。也常用于循环操作,比如已知经过的天数计算星期几。 - 假设场景: 调度系统将任务分配到不同的班次。如果有 3 个班次且任务按顺序编号,
task_number % 3可以决定任务落入哪个班次。
2. 比较运算符 (Comparison Operators)
比较运算符用于比较两个表达式并返回一个布尔结果(TRUE、FALSE 或 NULL)。它们常用于 WHERE 子句中以过滤数据。
- 等于 (
=): 检查两个操作数是否相等。 - 示例:
SELECT 'apple' = 'apple';结果为TRUE。SELECT 10 = 5;结果为FALSE。 - 实际用途: 查找在特定部门工作的所有员工 (
WHERE department_id = 101)。 - 不等于 (
<>或!=): 检查两个操作数是否不相等。 - 示例:
SELECT 'apple' <> 'orange';结果为TRUE。 - 实际用途: 检索所有未缺货的产品 (
WHERE status <> 'out_of_stock')。 - 大于 (
>): 检查第一个操作数是否大于第二个。 - 示例:
SELECT 10 > 5;结果为TRUE。 - 实际用途: 列出总金额大于 100 美元的所有订单 (
WHERE total_amount > 100)。 - 小于 (
<): 检查第一个操作数是否小于第二个。 - 示例:
SELECT 5 < 10;结果为TRUE。 - 实际用途: 查找所有 30 岁以下的员工 (
WHERE age < 30)。 - 大于或等于 (
>=): 检查第一个操作数是否大于或等于第二个。 - 示例:
SELECT 10 >= 10;结果为TRUE。 - 实际用途: 筛选消费了 500 美元及以上的客户 (
WHERE total_spent >= 500)。 - 小于或等于 (
<=): 检查第一个操作数是否小于或等于第二个。 - 示例:
SELECT 5 <= 10;结果为TRUE。 - 实际用途: 识别价格在 20 美元及以下的产品 (
WHERE price <= 20)。
3. 逻辑运算符 (Logical Operators)
逻辑运算符用于组合或修改布尔表达式。它们是在 WHERE 和 HAVING 子句中创建复杂过滤条件的基石。
- AND(与): 如果两个操作数均为
TRUE,则返回TRUE。 - 示例:
SELECT (10 > 5) AND (3 < 7);结果为TRUE。 - 实际用途: 查找既有库存且价格低于 50 美元的产品 (
WHERE quantity > 0 AND price < 50)。 - OR(或): 如果至少有一个操作数为
TRUE,则返回TRUE。 - 示例:
SELECT (10 > 5) OR (3 > 7);结果为TRUE。 - 实际用途: 筛选来自纽约或加州的用户 (
WHERE city = 'New York' OR city = 'California')。 - NOT(非): 反转操作数的布尔值。
NOT TRUE变为FALSE,NOT FALSE变为TRUE。 - 示例:
SELECT NOT (10 < 5);结果为TRUE。 - 实际用途: 检索所有尚未发货的订单 (
WHERE NOT status = 'shipped')。
4. 字符串运算符 (String Operators)
PostgreSQL 提供了专门用于操作和比较文本字符串的运算符。
- 拼接 (
||): 将两个或多个字符串连接在一起。 - 示例:
SELECT 'Hello' || ' ' || 'World';结果为'Hello World'。 - 实际业务场景: 将名字和姓氏合并为全名以在报表中显示。如果
first_name是 'John',last_name是 'Doe',则拼接'John' || ' ' || 'Doe'结果为 'John Doe'。 - 模式匹配 (
LIKE,ILIKE): 用于将文本值与指定的模式进行匹配。 LIKE是区分大小写的。ILIKE是不区分大小写的(PostgreSQL 特有)。- 模式匹配使用两个特殊的通配符:
%:匹配任何零个或多个字符的序列。_:匹配任何单个字符。- 示例 (
LIKE):SELECT 'apple' LIKE 'app%';结果为TRUE。SELECT 'Apple' LIKE 'app%';结果为FALSE。 - 示例 (
ILIKE):SELECT 'Apple' ILIKE 'app%';结果为TRUE。 - 实际用途: 搜索所有姓氏以 'Sm' 开头的客户 (
WHERE last_name LIKE 'Sm%'),或查找描述中任何位置包含 'widget' 的产品 (WHERE description ILIKE '%widget%')。 正则表达式匹配 (~,~*):提供更强大的正则表达式模式匹配功能。~:区分大小写匹配。~*:不区分大小写匹配。- 示例 (
~):SELECT 'foobar' ~ 'foo.*';结果为TRUE。SELECT 'Foobar' ~ 'foo.*';结果为FALSE。 - 示例 (
~*):SELECT 'Foobar' ~* 'foo.*';结果为TRUE。 - 实际用途: 验证电子邮件地址或从复杂的日志数据中提取特定模式。
5. 其他重要运算符 (Other Important Operators)
- IS NULL / IS NOT NULL: 检查
NULL值。NULL代表缺失或未知的数据,不能使用像=或<>这样的标准比较运算符来进行比较。 - 示例:
SELECT NULL IS NULL;结果为TRUE。SELECT 5 IS NOT NULL;结果为TRUE。 - 实际用途: 识别尚未分配送货司机的订单 (
WHERE driver_id IS NULL)。 - BETWEEN: 测试某个值是否在指定范围内(包含边界值)。
- 语法:
value BETWEEN low AND high - 示例:
SELECT 15 BETWEEN 10 AND 20;结果为TRUE。 - 实际用途: 查找价格在 20 到 50 美元之间的产品 (
WHERE price BETWEEN 20 AND 50)。 - IN: 测试某个值是否与值列表中的任何一个匹配。
- 语法:
value IN (value1, value2, ...) - 示例:
SELECT 'apple' IN ('apple', 'orange', 'banana');结果为TRUE。 - 实际用途: 检索特定客户 ID 列表下达的订单 (
WHERE customer_id IN (1, 5, 9))。 - NOT IN: 测试某个值是否与值列表中的任何一个都不匹配。
- 示例:
SELECT 'grape' NOT IN ('apple', 'orange', 'banana');结果为TRUE。
6. 运算符优先级 (Operator Precedence)
运算符优先级决定了表达式中运算的执行顺序。就像在标准数学中一样,乘除法先于加减法执行。可以使用括号 () 来覆盖默认的优先级。
理解优先级对于确保表达式按预期计算至关重要。
- 最高优先级: 括号
() - 其次: 一元运算符(例如,正负号
+,-) - 其次: 乘法
*,除法/,取模% - 其次: 加法
+,减法- - 其次: 字符串拼接
|| - 其次: 比较运算符
=,<>,>,<,>=,<= - 最低优先级(逻辑运算符):
NOT,AND,OR
示例: SELECT 5 + 3 * 2; 如果没有括号,计算顺序为 5 + (3 * 2) = 5 + 6 = 11。如果你想要先计算加法,需使用括号:SELECT (5 + 3) * 2; 结果为 8 * 2 = 16。
7. 实际案例与演示
假设我们有一个名为 products(产品)的表,包含以下结构和数据:
CREATE TABLE products (
product_id SERIAL PRIMARY KEY,
product_name VARCHAR(100),
category VARCHAR(50),
price DECIMAL(10, 2),
stock_quantity INTEGER,
last_updated DATE
);
INSERT INTO products (product_name, category, price, stock_quantity, last_updated) VALUES
('Laptop Pro', 'Electronics', 1200.00, 50, '2023-10-20'),
('Gaming Mouse', 'Electronics', 75.50, 200, '2023-10-18'),
('Mechanical Keyboard', 'Electronics', 120.00, 150, '2023-10-21'),
('Desk Chair Ergo', 'Furniture', 300.00, 30, '2023-10-15'),
('Monitor 27-inch', 'Electronics', 250.00, 80, '2023-10-22'),
('Wireless Earbuds', 'Audio', 99.99, 300, '2023-10-19'),
('Office Desk L-shape', 'Furniture', 450.00, 20, '2023-10-16'),
('USB-C Hub', 'Accessories', 35.00, 100, '2023-10-20'),
('External SSD 1TB', 'Storage', 150.00, 70, '2023-10-17');7.1 使用算术运算符
计算每种产品的库存总价值:
SELECT
product_name,
price,
stock_quantity,
price * stock_quantity AS total_stock_value -- 乘法运算符
FROM
products;此查询使用 * 运算符将每种产品的 price 乘以 stock_quantity,得出可用库存的总货币价值。
将所有 'Electronics'(电子产品)的价格提高 10%:
UPDATE products
SET price = price * 1.10 -- 用于增加 10% 的乘法运算符
WHERE category = 'Electronics';
-- 验证更改(在执行 UPDATE 后运行)
SELECT product_name, price FROM products WHERE category = 'Electronics';7.2 使用比较和逻辑运算符
查找价格超过 100 美元的 'Electronics'(电子产品):
SELECT
product_name,
category,
price
FROM
products
WHERE
category = 'Electronics' AND price > 100.00; -- 结合 = 和 >,并使用 AND 连接列出库存数量在 50 到 150 之间(含)的产品:
SELECT
product_name,
stock_quantity
FROM
products
WHERE
stock_quantity BETWEEN 50 AND 150; -- BETWEEN 运算符识别属于 'Furniture'(家具)或 'Audio'(音频)类别的产品:
SELECT
product_name,
category
FROM
products
WHERE
category IN ('Furniture', 'Audio'); -- IN 运算符7.3 使用字符串运算符
拼接产品名称和类别以便于展示:
SELECT
product_id,
product_name || ' (' || category || ')' AS product_details -- 拼接运算符
FROM
products;|| 运算符将产品名称、带括号的字面量字符串和类别组合成一个描述性更强的单一字符串。
查找名称中包含 'Desk' 的产品(不区分大小写):
SELECT
product_name
FROM
products
WHERE
product_name ILIKE '%Desk%'; -- ILIKE 结合两端的 % 通配符这将返回 'Desk Chair Ergo' 和 'Office Desk L-shape'。
7.4 使用 IS NULL / IS NOT NULL
假设对于新添加的产品,last_updated 字段有时可能为 NULL。首先,我们更新一个产品使其 last_updated 为 NULL 作为演示:
UPDATE products
SET last_updated = NULL
WHERE product_name = 'USB-C Hub';
-- 现在,检索 last_updated 日期为 NULL 的产品:
SELECT
product_name,
last_updated
FROM
products
WHERE
last_updated IS NULL; -- IS NULL 运算符此查询能正确识别出 'USB-C Hub' 具有 NULL 值的更新日期。