← All Posts

SQL(结构化查询语言)数据库安装与使用

首先推荐一个不错的SQL语句指导和练习网站:SQLZoo

PostgreSQL 数据库安装#

PostgreSQL: The World’s Most Advanced Open Source Relational Database

PostgreSQL 是一个开源关系型数据库管理系统(Relational Database Management System, RDBMS)
以稳定性、标准兼容性和丰富的数据类型支持而闻名, 被广泛应用于 Web 开发、数据分析以及企业级应用。

  • 安装后后添加路径到环境变量
D:\Database\PostgreSQL\bin
  • 验证版本
Terminal window
psql --version

初识 表、数据库、SQL#

表的基础结构#

表(Table)是数据库中存储数据的基本单位,可以理解为一个横纵方向的二维表格。

例如用户信息表:

idusernameemail
1Alicealice@example.com
2Bobbob@example.com
3Charliecharlie@example.com

其中:

  • 每一列(Column)表示一个字段(Field)
  • 每一行(Row)表示一条记录(Record)
  • 每张表通常会有主键(Primary Key)用于唯一标识记录

数据库的基础结构#

数据库(Database)是多个表的集合,用于组织和管理数据。

一个简单的网站数据库可能包含多个表:

mydb
├── users
├── articles
├── comments
└── categories

其中:

  • users 表存储用户信息
  • articles 表存储文章信息
  • comments 表存储评论信息
  • categories 表存储分类信息

数据库负责维护这些表之间的关系,并保证数据的一致性与安全性。


SQL 基础概念#

SQL(Structured Query Language,结构化查询语言)是操作关系型数据库的标准语言。

通过 SQL 可以完成:

  • 创建数据库和表(CREATE)
  • 查询数据(SELECT)
  • 插入数据(INSERT)
  • 更新数据(UPDATE)
  • 删除数据(DELETE)

例如:

SELECT * FROM users;

表示查询 users 表中的所有数据。 SQL 是学习 PostgreSQL、MySQL、SQLite 等关系型数据库的基础工具。


PostgreSQL 基础操作#

1. 创建数据库与表#

-- 创建数据库
CREATE DATABASE mydb;
-- 切换数据库
\c mydb
-- 创建表
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(60) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
age INT,
created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
  • 注意:列的格式为:字段名 数据类型[(长度)] [约束/修饰符]

2. 删除数据库与表,或清空表#

-- 删除数据库(不能删除当前连接的数据库)
DROP DATABASE mydb;
-- 删除表(包括表结构和数据)
DROP TABLE exTable;
-- 清空表数据,但保留表结构 (比 DELETE 快,但不记录行日志)
TRUNCATE TABLE exTable;--

3. 表添加新列,修改数据类型#

-- 添加新列:
ALTER TABLE exTable ADD COLUMN age INT;
-- 修改数据类型:
ALTER TABLE exTable ALTER COLUMN email TYPE VARCHAR(255);

4. 查增改删数据#

-- 查询所有数据
SELECT * FROM exTable;
-- 条件查询
SELECT username, email
FROM exTable
WHERE id > 1;
-- 模糊查询 (ILIKE 不区分大小写,PostgreSQL 特色)
SELECT username, email FROM exTable WHERE username ILIKE 'tech%';
-- 排序与限制,默认升序,DESC为降序
SELECT * FROM exTable
ORDER BY created_time DESC
LIMIT 6;

-- 插入一行数据
INSERT INTO exTable (username, email)
VALUES ('alice', 'alice@example.com');
-- 插入多行
INSERT INTO exTable (username, email)
VALUES
('bob', 'bob@example.com'),
('charlie', 'charlie@example.com');

UPDATE exTable
SET email = 'alice_new@example.com'
WHERE username = 'alice';
  • 对表进行修改时,务必限定范围,否则会更新全表信息

DELETE FROM exTable
WHERE username = 'charlie';

PostgreSQL 进阶基础(T+1)#

前置:已掌握建表、增删改查基础操作
本章目标:写出更精准的查询,理解数据约束,初步接触多表关联


多条件组合查询:AND / OR / NOT#

-- AND:同时满足
SELECT * FROM users
WHERE age >= 18 AND age <= 30;
-- OR:满足其中一个
SELECT * FROM users
WHERE username = 'alice' OR username = 'bob';
-- NOT:排除
SELECT * FROM users
WHERE NOT age < 18;

范围与列表:BETWEEN / IN#

-- BETWEEN(含两端)
SELECT * FROM users
WHERE age BETWEEN 18 AND 30;
-- IN(等同于多个 OR,更简洁)
SELECT * FROM users
WHERE username IN ('alice', 'bob', 'charlie');
-- NOT IN(排除列表)
SELECT * FROM users
WHERE username NOT IN ('alice', 'bob');

空值判断:IS NULL / IS NOT NULL#

-- 查找没有填写年龄的用户(注意:不能用 = NULL)
SELECT * FROM users
WHERE age IS NULL;
-- 查找已填写年龄的用户
SELECT * FROM users
WHERE age IS NOT NULL;

NULL 不等于空字符串 '',也不等于 0,是”未知值”,只能用 IS NULL 判断


聚合函数:对一组数据做统计#

函数作用
COUNT()计数
SUM()求和
AVG()平均值
MAX()最大值
MIN()最小值
-- 一共有多少用户
SELECT COUNT(*) FROM users;
-- 用户的平均年龄
SELECT AVG(age) FROM users;
-- 年龄最大和最小的用户
SELECT MAX(age), MIN(age) FROM users;
-- 注意:COUNT(*) 计所有行,COUNT(age) 会跳过 NULL
SELECT COUNT(*), COUNT(age) FROM users;

GROUP BY:分组统计#

把数据按某列分组,再对每组做聚合计算

-- 先创建一张订单表来演示
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
username VARCHAR(60) NOT NULL,
product VARCHAR(60),
amount INT,
created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO orders (username, product, amount) VALUES
('alice', 'book', 120),
('alice', 'pen', 30),
('bob', 'book', 120),
('bob', 'bag', 200),
('charlie','pen', 30);
-- 每个用户各消费了多少次
SELECT username, COUNT(*) AS order_count
FROM orders
GROUP BY username;
-- 每个用户的总消费金额
SELECT username, SUM(amount) AS total_spent
FROM orders
GROUP BY username;

输出示例:

usernametotal_spent
alice150
bob320
charlie30


查询执行顺序(重要!)#

很多初学者写出报错 SQL,往往是因为搞错了执行顺序:

FROM → 确定数据来源
WHERE → 过滤原始行
GROUP BY → 分组
HAVING → 过滤分组结果
SELECT → 选取列(别名在这里才生效)
ORDER BY → 排序
LIMIT → 限制条数
-- 常见错误示例:WHERE 里用了 SELECT 里定义的别名
-- ❌ 错误:WHERE 在 SELECT 之前执行,total_spent 还不存在
SELECT username, SUM(amount) AS total_spent
FROM orders
WHERE total_spent > 100 -- 报错!
GROUP BY username;
-- ✅ 正确:用 HAVING
SELECT username, SUM(amount) AS total_spent
FROM orders
GROUP BY username
HAVING SUM(amount) > 100;

外键(Foreign Key):表之间的纽带#

外键用于约束两张表之间的关系,防止出现”孤儿数据”

-- 重建 users 表(如果已存在先删除)
DROP TABLE IF EXISTS orders;
DROP TABLE IF EXISTS users;
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(60) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL
);
-- orders 表的 user_id 指向 users 表的 id
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
user_id INT REFERENCES users(id), -- 外键
product VARCHAR(60),
amount INT
);

外键的保护效果:

INSERT INTO users (username, email) VALUES ('alice', 'alice@example.com');
-- ✅ alice 的 id 是 1,可以正常插入
INSERT INTO orders (user_id, product, amount) VALUES (1, 'book', 120);
-- ❌ 报错:user_id=999 在 users 表里不存在
INSERT INTO orders (user_id, product, amount) VALUES (999, 'pen', 30);


给列和表起别名:AS#

-- 列别名(让输出更易读)
SELECT
username AS 用户名,
SUM(amount) AS 总消费
FROM orders
JOIN users ON orders.user_id = users.id
GROUP BY username;
-- 表别名(简化长表名,多表联查时常用)
SELECT u.username, o.product, o.amount
FROM users AS u
JOIN orders AS o ON u.id = o.user_id;

本章练习#

用以下两张表完成练习:

-- 准备数据
INSERT INTO users (username, email) VALUES
('alice', 'alice@example.com'),
('bob', 'bob@example.com'),
('charlie', 'charlie@example.com');
INSERT INTO orders (user_id, product, amount) VALUES
(1, 'book', 120),
(1, 'pen', 30),
(2, 'book', 120),
(2, 'bag', 200);
-- charlie 没有订单
  1. 查询所有用户名和他们的订单总金额,按总金额降序排列
  2. 找出总消费超过 100 的用户
  3. 查询所有用户,没有订单的也要显示(提示:LEFT JOIN)
  4. 统计每种商品各卖出了几次

本章知识结构#

T+1 SQL基础
├── 条件查询
│ ├── AND / OR / NOT
│ ├── BETWEEN / IN
│ └── IS NULL / IS NOT NULL
├── 聚合统计
│ ├── COUNT / SUM / AVG / MAX / MIN
│ ├── GROUP BY
│ └── HAVING
├── 查询执行顺序
│ └── FROM→WHERE→GROUP BY→HAVING→SELECT→ORDER BY→LIMIT
└── 多表关联
├── 外键 REFERENCES
├── INNER JOIN
├── LEFT JOIN
└── 列/表别名 AS