SELECT 查询
SELECT 是 SQL 中最常用的语句,用于从数据库中查询数据。本章将详细介绍 SELECT 的各种用法。
基本 SELECT
查询所有列
使用 * 查询表中的所有列:
SELECT * FROM users;
* 表示所有列,这在探索数据时很方便,但在生产代码中不推荐使用,因为:
- 可能返回不需要的列,浪费资源
- 表结构变化时可能产生意外结果
查询指定列
明确列出需要的列名:
SELECT name, email FROM users;
这是推荐的做法,因为:
- 只返回需要的数据,效率更高
- 代码更清晰,易于理解
- 表结构变化时不会受影响
列别名
使用 AS 关键字为列设置别名:
SELECT
name AS 姓名,
email AS 邮箱,
age AS 年龄
FROM users;
AS 关键字可以省略:
SELECT name 姓名, email 邮箱 FROM users;
别名的作用:
- 使结果更易读
- 为计算列命名
- 解决列名冲突
DISTINCT 去重
使用 DISTINCT 关键字去除重复值:
-- 查询所有不同的城市
SELECT DISTINCT city FROM users;
-- 多列去重(组合唯一)
SELECT DISTINCT city, country FROM users;
去重的原理:比较所有选中列的值,完全相同才认为是重复。
-- 示例数据
-- | city | country |
-- |---------|---------|
-- | 北京 | 中国 |
-- | 上海 | 中国 |
-- | 北京 | 中国 | <- 与第一行重复
SELECT DISTINCT city, country FROM users;
-- 结果:
-- | city | country |
-- |---------|---------|
-- | 北京 | 中国 |
-- | 上海 | 中国 |
LIMIT 限制结果
基本用法
限制返回的行数:
-- MySQL / PostgreSQL / SQLite
SELECT * FROM users LIMIT 10;
-- SQL Server
SELECT TOP 10 * FROM users;
-- Oracle
SELECT * FROM users WHERE ROWNUM <= 10;
分页查询
结合 OFFSET 实现分页:
-- MySQL / PostgreSQL / SQLite
-- 每页 10 条,第 2 页(跳过前 10 条)
SELECT * FROM users LIMIT 10 OFFSET 10;
-- 简写形式(MySQL)
SELECT * FROM users LIMIT 10, 10; -- LIMIT offset, count
分页公式:
-- 第 page 页,每页 size 条
SELECT * FROM users LIMIT size OFFSET (page - 1) * size;
计算列
SELECT 可以包含计算表达式:
算术运算
SELECT
product_name,
price,
quantity,
price * quantity AS total_price,
price * 0.9 AS discount_price
FROM order_items;
支持的运算符:+、-、*、/
字符串拼接
-- MySQL
SELECT CONCAT(first_name, ' ', last_name) AS full_name FROM users;
-- PostgreSQL / Oracle
SELECT first_name || ' ' || last_name AS full_name FROM users;
-- SQL Server
SELECT first_name + ' ' + last_name AS full_name FROM users;
条件表达式
使用 CASE WHEN 进行条件判断:
SELECT
name,
score,
CASE
WHEN score >= 90 THEN '优秀'
WHEN score >= 80 THEN '良好'
WHEN score >= 60 THEN '及格'
ELSE '不及格'
END AS grade
FROM students;
常用函数
字符串函数
-- 转换大小写
SELECT UPPER(name) FROM users; -- 大写
SELECT LOWER(name) FROM users; -- 小写
-- 字符串长度
SELECT LENGTH(name) FROM users; -- MySQL / PostgreSQL
SELECT LEN(name) FROM users; -- SQL Server
-- 截取字符串
SELECT SUBSTRING(name, 1, 3) FROM users; -- 从第1个字符开始,取3个字符
SELECT LEFT(name, 3) FROM users; -- 取左边3个字符
SELECT RIGHT(name, 3) FROM users; -- 取右边3个字符
-- 去除空格
SELECT TRIM(name) FROM users; -- 去除两端空格
SELECT LTRIM(name) FROM users; -- 去除左边空格
SELECT RTRIM(name) FROM users; -- 去除右边空格
数值函数
-- 四舍五入
SELECT ROUND(3.14159, 2); -- 3.14
-- 向上取整
SELECT CEIL(3.14); -- 4
-- 向下取整
SELECT FLOOR(3.14); -- 3
-- 绝对值
SELECT ABS(-10); -- 10
-- 取模
SELECT MOD(10, 3); -- 1
日期函数
-- 当前日期和时间
SELECT NOW(); -- MySQL / PostgreSQL
SELECT GETDATE(); -- SQL Server
SELECT SYSDATE; -- Oracle
-- 当前日期
SELECT CURRENT_DATE; -- PostgreSQL / MySQL
-- 提取日期部分
SELECT YEAR(created_at) FROM orders; -- 提取年份
SELECT MONTH(created_at) FROM orders; -- 提取月份
SELECT DAY(created_at) FROM orders; -- 提取日期
-- 日期计算
SELECT DATE_ADD(NOW(), INTERVAL 7 DAY); -- MySQL:加7天
SELECT created_at + INTERVAL '7 days' FROM orders; -- PostgreSQL
类型转换
-- CAST 函数(标准 SQL)
SELECT CAST(price AS CHAR) FROM products;
SELECT CAST('123' AS INT);
-- MySQL 特有
SELECT CONVERT(price, CHAR) FROM products;
NULL 值处理
NULL 表示缺失或未知的值,需要特殊处理:
NULL 的特点
-- NULL 与任何值比较都返回 NULL(不是 true 或 false)
SELECT * FROM users WHERE age = NULL; -- 错误!不会返回任何结果
SELECT * FROM users WHERE age != NULL; -- 错误!不会返回任何结果
-- 正确的 NULL 比较
SELECT * FROM users WHERE age IS NULL; -- 查询 NULL 值
SELECT * FROM users WHERE age IS NOT NULL; -- 查询非 NULL 值
COALESCE 函数
返回第一个非 NULL 值:
SELECT
name,
COALESCE(phone, mobile, '无联系方式') AS contact
FROM users;
IFNULL / NVL / ISNULL
不同数据库的 NULL 处理函数:
-- MySQL
SELECT IFNULL(phone, '未知') FROM users;
-- Oracle
SELECT NVL(phone, '未知') FROM users;
-- SQL Server
SELECT ISNULL(phone, '未知') FROM users;
NULLIF 函数
如果两个值相等则返回 NULL:
-- 避免除以零错误
SELECT total / NULLIF(count, 0) AS average FROM orders;
表别名
使用 AS 为表设置别名,简化 SQL 并提高可读性:
SELECT u.name, o.order_date
FROM users AS u
JOIN orders AS o ON u.id = o.user_id;
-- AS 可以省略
SELECT u.name, o.order_date
FROM users u
JOIN orders o ON u.id = o.user_id;
表别名的作用:
- 简化长表名
- 消除多表连接时的列名冲突
- 自连接时区分同一表的不同实例
小结
本章我们学习了:
- 基本 SELECT 语法
- 使用 DISTINCT 去重
- 使用 LIMIT 限制结果
- 计算列和表达式
- 常用函数(字符串、数值、日期)
- NULL 值处理
- 表别名
练习
- 查询 users 表的 name 和 email 列,并为它们设置中文别名
- 查询 products 表中不同的 category
- 计算订单表中每个订单的总金额(单价 × 数量)
- 查询 users 表的前 20 条记录
- 使用 CASE WHEN 将分数转换为等级