Skip to content

PostgreSQL 逻辑运算符

概述

PostgreSQL 支持标准的逻辑运算符,用于在 SQL 查询中执行布尔逻辑操作。与传统的二值逻辑(true/false)不同,PostgreSQL 使用三值逻辑系统,包括 truefalsenull(表示"未知")。

PostgreSQL 的三值逻辑系统是为了处理数据库中的 NULL 值而设计的,这使得逻辑运算更加符合关系数据库的实际需求。 :::

基本逻辑运算符

PostgreSQL 提供三个主要的逻辑运算符:

运算符语法返回类型描述
ANDboolean AND booleanboolean逻辑与运算
ORboolean OR booleanboolean逻辑或运算
NOTNOT booleanboolean逻辑非运算

基本语法示例

sql
-- 基本 AND 运算
SELECT true AND true;    -- 结果: true
SELECT true AND false;   -- 结果: false

-- 基本 OR 运算
SELECT true OR false;    -- 结果: true
SELECT false OR false;   -- 结果: false

-- 基本 NOT 运算
SELECT NOT true;         -- 结果: false
SELECT NOT false;        -- 结果: true
sql
-- 在 WHERE 子句中使用逻辑运算符
SELECT * FROM employees
WHERE age > 25 AND department = 'IT';

-- 使用 OR 运算符
SELECT * FROM products
WHERE price > 100 OR category = 'Electronics';

-- 使用 NOT 运算符
SELECT * FROM customers
WHERE NOT city = 'Beijing';

三值逻辑真值表

AND 和 OR 运算符真值表

aba AND ba OR b
TRUETRUETRUETRUE
TRUEFALSEFALSETRUE
TRUENULLNULLTRUE
FALSEFALSEFALSEFALSE
FALSENULLFALSENULL
NULLNULLNULLNULL

NOT 运算符真值表

aNOT a
TRUEFALSE
FALSETRUE
NULLNULL

特别注意 NULL 值的处理:

  • TRUE AND NULL 结果为 NULL
  • FALSE OR NULL 结果为 NULL
  • NOT NULL 结果仍为 NULL :::

实际业务场景示例

示例 1:员工筛选系统

假设我们有一个员工表,需要根据多个条件筛选员工:

sql
-- 创建示例表
CREATE TABLE employees (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100),
    age INTEGER,
    department VARCHAR(50),
    salary DECIMAL(10,2),
    is_active BOOLEAN
);

-- 插入示例数据
INSERT INTO employees (name, age, department, salary, is_active) VALUES
('张三', 28, 'IT', 8000.00, true),
('李四', 32, 'HR', 6500.00, true),
('王五', 25, 'IT', 7500.00, false),
('赵六', NULL, 'Finance', 9000.00, true),
('孙七', 30, NULL, 7000.00, true);

问题陈述:筛选出年龄大于 25 岁且在 IT 部门的活跃员工。

解决方案

sql
SELECT name, age, department, salary
FROM employees
WHERE age > 25 AND department = 'IT' AND is_active = true;

分析过程

  1. age > 25:筛选年龄大于 25 的员工
  2. department = 'IT':限定部门为 IT
  3. is_active = true:确保员工状态为活跃
  4. 使用 AND 运算符确保所有条件都必须满足

输入和输出

sql
-- 输入数据(employees 表)
name  | age | department | salary  | is_active
------|-----|------------|---------|----------
张三  | 28  | IT         | 8000.00 | true
李四  | 32  | HR         | 6500.00 | true
王五  | 25  | IT         | 7500.00 | false
赵六  | NULL| Finance    | 9000.00 | true
孙七  | 30  | NULL       | 7000.00 | true

-- 输出结果
name | age | department | salary
-----|-----|------------|--------
张三 | 28  | IT         | 8000.00

示例 2:处理 NULL 值的复杂查询

问题陈述:查找所有可能符合条件的员工,包括年龄未知但部门明确的员工。

解决方案

sql
-- 使用 OR 运算符处理 NULL 值
SELECT name, age, department, salary
FROM employees
WHERE (age > 25 OR age IS NULL) AND department IS NOT NULL;

分析过程

  1. age > 25 OR age IS NULL:包含年龄大于 25 或年龄未知的员工
  2. department IS NOT NULL:确保部门信息不为空
  3. 使用 IS NULLIS NOT NULL 来明确处理 NULL 值

输入和输出

sql
-- 输出结果
name | age  | department | salary
-----|------|------------|--------
张三 | 28   | IT         | 8000.00
李四 | 32   | HR         | 6500.00
赵六 | NULL | Finance    | 9000.00

示例 3:复杂的业务逻辑组合

问题陈述:查找高薪员工或 IT 部门的活跃员工。

解决方案

sql
SELECT name, age, department, salary, is_active
FROM employees
WHERE salary > 8000 OR (department = 'IT' AND is_active = true);

分析过程

  1. salary > 8000:薪资超过 8000 的员工
  2. department = 'IT' AND is_active = true:IT 部门的活跃员工
  3. 使用括号明确运算优先级
  4. OR 运算符使得满足任一条件的员工都会被选中

输入和输出

sql
-- 输出结果
name | age  | department | salary  | is_active
-----|------|------------|---------|----------
张三 | 28   | IT         | 8000.00 | true
赵六 | NULL | Finance    | 9000.00 | true

NULL 值处理的最佳实践

使用 COALESCE 函数

当需要为 NULL 值提供默认值时,可以使用 COALESCE 函数:

sql
-- 为 NULL 年龄提供默认值
SELECT name, COALESCE(age, 0) as age, department
FROM employees
WHERE COALESCE(age, 0) > 25 AND department IS NOT NULL;

使用 CASE 语句处理复杂逻辑

sql
SELECT name, age, department,
       CASE
         WHEN age IS NULL THEN '年龄未知'
         WHEN age > 30 THEN '资深员工'
         WHEN age > 25 THEN '中级员工'
         ELSE '初级员工'
       END as employee_level
FROM employees;

运算符优先级和交换性

TIP

  • AND 和 OR 运算符具有交换性,即 A AND B 等价于 B AND A
  • 但不能保证左操作数在右操作数之前进行求值
  • 使用括号可以明确控制运算顺序 :::

优先级示例

sql
-- 没有括号的情况(AND 优先级高于 OR)
SELECT * FROM employees
WHERE department = 'IT' OR department = 'HR' AND salary > 7000;

-- 等价于
SELECT * FROM employees
WHERE department = 'IT' OR (department = 'HR' AND salary > 7000);

-- 使用括号明确意图
SELECT * FROM employees
WHERE (department = 'IT' OR department = 'HR') AND salary > 7000;

性能考虑

索引利用

sql
-- 创建索引以优化逻辑运算查询
CREATE INDEX idx_employees_dept_salary ON employees(department, salary);
CREATE INDEX idx_employees_age_active ON employees(age, is_active);

-- 优化后的查询
SELECT * FROM employees
WHERE department = 'IT' AND salary > 7000;

查询优化流程

常见错误和注意事项

错误示例 1:NULL 值比较

sql
-- ❌ 错误:这样无法匹配 NULL 值
SELECT * FROM employees WHERE age = NULL;

-- ✅ 正确:使用 IS NULL
SELECT * FROM employees WHERE age IS NULL;

错误示例 2:忽略运算符优先级

sql
-- ❌ 可能产生意外结果
SELECT * FROM employees
WHERE department = 'IT' OR department = 'HR' AND salary > 7000;

-- ✅ 使用括号明确意图
SELECT * FROM employees
WHERE (department = 'IT' OR department = 'HR') AND salary > 7000;

错误示例 3:布尔值与字符串混淆

sql
-- ❌ 错误:将布尔值当作字符串
SELECT * FROM employees WHERE is_active = 'true';

-- ✅ 正确:使用布尔字面量
SELECT * FROM employees WHERE is_active = true;

实际应用场景

电商系统商品筛选

sql
-- 创建商品表
CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    name VARCHAR(200),
    price DECIMAL(10,2),
    category VARCHAR(100),
    in_stock BOOLEAN,
    rating DECIMAL(3,2)
);

-- 复杂筛选条件
SELECT name, price, category, rating
FROM products
WHERE (category = 'Electronics' OR category = 'Computers')
  AND price BETWEEN 100 AND 1000
  AND in_stock = true
  AND (rating >= 4.0 OR rating IS NULL);

用户权限系统

sql
-- 用户权限表
CREATE TABLE user_permissions (
    user_id INTEGER,
    can_read BOOLEAN,
    can_write BOOLEAN,
    can_delete BOOLEAN,
    is_admin BOOLEAN
);

-- 检查用户是否有写权限或管理员权限
SELECT user_id
FROM user_permissions
WHERE can_write = true OR is_admin = true;

-- 检查用户是否有完整权限
SELECT user_id
FROM user_permissions
WHERE can_read = true AND can_write = true AND can_delete = true;

通过这些示例,我们可以看到逻辑运算符在实际业务场景中的重要作用。正确理解和使用三值逻辑系统,能够帮助我们编写更准确、更高效的 SQL 查询。

在处理包含 NULL 值的数据时,始终要考虑三值逻辑的影响,使用适当的 NULL 处理函数和条件来确保查询结果的准确性。