PostgreSQL 新手入门教程 – wiki基地


PostgreSQL 新手入门:从零开始征服强大的开源数据库

欢迎来到数据库的世界!如果你正在寻找一个强大、可靠、功能丰富且开源的数据库系统,那么 PostgreSQL 无疑是一个绝佳的选择。它被广泛应用于各种规模的项目中,从小型个人应用到大型企业系统。

本篇文章将为你提供一份详细的 PostgreSQL 入门指南,即使你没有任何数据库经验,也能跟随我们的脚步,逐步掌握 PostgreSQL 的基本概念和操作。

预计阅读时间: 较长(本文旨在提供全面指导,字数较多)

第 1 章:初识数据库与 PostgreSQL

在深入学习 PostgreSQL 之前,我们先来理解一些基础概念。

1.1 什么是数据库?

想象一下一个大型的、结构化的文件柜。数据库就是这样一个系统,用来存储、管理和组织数据。它可以让你方便地添加新数据、查找现有数据、更新数据或删除数据。

1.2 什么是关系型数据库(RDBMS)?

关系型数据库是一种特定类型的数据库,它使用表格(Table)来组织数据。每个表格由行(Row)和列(Column)组成。表格之间可以通过共同的列建立关系。

关系型数据库管理系统(RDBMS,Relational Database Management System)是用来创建、维护和操作关系型数据库的软件。常见的 RDBMS 包括 PostgreSQL、MySQL、Oracle、SQL Server 等。

关系型数据库的核心优势在于其结构化和关系性,这使得数据一致性、查询灵活性和数据完整性得到很好的保障。

1.3 为什么选择 PostgreSQL?

PostgreSQL,通常被昵称为 “Postgres”,是一个免费且开源的关系型数据库系统。它拥有许多优点,使其成为许多开发者和企业的首选:

  • 强大且功能丰富: 它支持复杂的查询、多种数据类型(包括结构化、半结构化数据)、索引、事务、视图、存储过程等企业级特性。
  • 高度兼容 SQL 标准: PostgreSQL 非常遵循 SQL 标准,这意味着你学习的 SQL 知识可以在其他符合标准的数据库中复用。
  • 可靠性和稳定性: 它经过了数十年的发展和社区的严格测试,具有出色的稳定性和数据完整性保障。
  • 可扩展性: PostgreSQL 可以通过各种方式进行扩展,支持处理大量数据和高并发负载。
  • 活跃的社区: 拥有庞大且活跃的社区,遇到问题时容易找到帮助和资源。
  • 开源免费: 无需支付许可费用即可使用所有功能。

第 2 章:安装 PostgreSQL

开始使用 PostgreSQL 的第一步是将其安装到你的计算机上。安装过程因操作系统而异,但通常都非常直观。

2.1 Windows 系统安装

对于 Windows 用户,最简单的方式是下载官方提供的图形化安装程序:

  1. 访问 PostgreSQL 官方下载页面:https://www.postgresql.org/download/windows/
  2. 下载与你系统兼容的最新版本安装程序。
  3. 运行下载的 .exe 文件。
  4. 按照安装向导的提示进行操作。安装过程中,你需要选择安装的组件(至少包含 PostgreSQL Server 和 pgAdmin),设置数据目录,设置数据库超级用户(postgres)的密码,以及指定端口号(默认是 5432)。记住这个密码,后续连接数据库时需要用到。
  5. 安装完成后,通常会有一个 Stack Builder 工具,你可以选择安装额外的驱动或工具,新手可以暂时跳过。

2.2 macOS 系统安装

macOS 用户有几种安装方式:

  1. 使用 Homebrew (推荐): 如果你使用 Homebrew 包管理器,安装 PostgreSQL 变得非常简单。打开终端,运行命令:
    bash
    brew install postgresql

    安装完成后,Homebrew 会提示你如何启动和停止 PostgreSQL 服务。
  2. 使用官方图形化安装程序: 类似于 Windows,你也可以从官方网站下载 macOS 的安装程序:https://www.postgresql.org/download/macosx/。按照提示步骤安装即可。

2.3 Linux 系统安装

大多数 Linux 发行版的官方软件仓库都包含了 PostgreSQL。使用发行版自带的包管理器安装是最方便的方式。

  • Debian/Ubuntu:
    bash
    sudo apt update
    sudo apt install postgresql postgresql-contrib
  • Fedora/CentOS/RHEL:
    bash
    sudo dnf install postgresql-server postgresql-contrib # Fedora 30+
    # 或者对于较老的 CentOS/RHEL:
    # sudo yum install postgresql-server postgresql-contrib
    sudo postgresql-setup initdb # 初始化数据库
    sudo systemctl enable postgresql # 设置开机自启
    sudo systemctl start postgresql # 启动服务
  • Arch Linux:
    bash
    sudo pacman -S postgresql
    initdb --locale $LANG -E UTF8 -D /var/lib/postgres/data # 初始化数据库
    sudo systemctl enable postgresql
    sudo systemctl start postgresql

安装完成后,无论在哪种系统上,通常都会创建一个名为 postgres 的超级用户和一个同名的数据库。你需要设置 postgres 用户的密码,以便后续连接和管理。

  • Linux/macOS (使用终端):
    bash
    sudo -u postgres psql

    进入 psql 命令行工具后,执行:
    sql
    \password postgres

    然后输入并确认新密码。完成后输入 \q 退出 psql。
  • Windows (使用 pgAdmin 或通过其他方式): Windows 安装程序通常在安装过程中就要求你设置 postgres 用户的密码。如果需要修改,可以在安装后使用 pgAdmin 或其他工具。

第 3 章:连接 PostgreSQL 数据库

安装完成后,你需要学习如何连接到数据库服务器并与其交互。有两种主要的方式:命令行工具 psql 和图形化工具 pgAdmin

3.1 使用 psql (命令行工具)

psql 是 PostgreSQL 官方提供的强大的命令行客户端工具。它非常适合执行快速命令、运行脚本以及进行一些高级管理。

  • 启动 psql:
    打开终端或命令提示符,输入 psql。默认情况下,它会尝试使用当前操作系统用户名连接到本地的 postgres 数据库。
    bash
    psql -U postgres # 使用 postgres 用户连接
    psql -U postgres -d your_database # 使用 postgres 用户连接到指定数据库
    psql -h your_host -U your_user -d your_database -p your_port # 连接到远程或非默认端口的数据库

    连接时会提示你输入密码。

  • psql 基本命令 (以 \ 开头):

    • \l: 列出所有数据库。
    • \c [数据库名]: 连接到指定的数据库。
    • \dt: 列出当前数据库中的所有表。
    • \d [表名]: 描述表的结构(列、类型、索引等)。
    • \dn: 列出所有模式 (Schema)。
    • \du: 列出所有用户/角色。
    • \?: 获取 psql 命令帮助。
    • \q: 退出 psql。

    psql 中,你可以直接输入 SQL 语句,以分号 ; 结尾执行。

3.2 使用 pgAdmin (图形化工具)

pgAdmin 是一个流行的开源图形化管理工具,提供了一个友好的用户界面来管理 PostgreSQL 数据库。Windows 和 macOS 的官方安装程序通常会捆绑安装它。Linux 用户可能需要单独安装。

  • 启动 pgAdmin: 找到并运行 pgAdmin 应用程序。
  • 添加服务器连接:

    1. 在左侧的浏览器面板中,右键点击 “Servers” 或 “Connections”。
    2. 选择 “Create” -> “Server…”。
    3. 在 “General” 选项卡中,给你的连接起一个名字(例如 “My Local Postgres”)。
    4. 在 “Connection” 选项卡中:
      • Host name/address: 填写数据库服务器的地址。如果是本地,通常是 localhost127.0.0.1
      • Port: 填写数据库服务器的端口号(默认 5432)。
      • Maintenance database: 填写维护数据库的名称(通常是 postgres)。
      • Username: 填写连接用的数据库用户名(例如 postgres)。
      • Password: 填写对应用户的密码。你可以选择保存密码。
    5. 点击 “Save”。
  • 使用 pgAdmin:
    连接成功后,你会在浏览器面板中看到你的服务器。展开服务器,你可以看到 Databases, Login/Group Roles 等。展开 Databases,可以看到 postgres 数据库以及你创建的其他数据库。展开某个数据库,可以看到 Schemas, Tables, Views 等对象。
    要执行 SQL 查询,选中一个数据库,然后在顶部菜单栏中找到 “Tools” -> “Query Tool”,或者右键点击数据库或模式,选择 “Query Tool”。这将打开一个 SQL 编辑器面板,你可以在其中编写和执行 SQL 语句。

对于新手来说,pgAdmin 提供了一个更直观的方式来浏览数据库结构和执行查询,可以与 psql 结合使用。

第 4 章:PostgreSQL 基本概念与 SQL 基础

现在你已经安装并连接到 PostgreSQL,是时候学习一些核心概念和最基本的 SQL 语句了。

4.1 数据库对象层级

在 PostgreSQL 中,对象的层级通常是:

  • 服务器 (Server): 运行 PostgreSQL 服务的实例。
  • 数据库 (Database): 服务器下独立的容器,包含自己的模式、表、索引等。
  • 模式 (Schema): 数据库内的命名空间,用于组织表和其他数据库对象。默认有一个 public 模式。使用模式可以避免对象名称冲突,方便管理。
  • 表 (Table): 数据存储的基本单元,由行和列组成。
  • 列 (Column): 定义表中存储的数据类型和属性。
  • 行 (Row): 表中的一条记录,包含各列的具体数据。

4.2 数据类型 (Data Types)

为列选择合适的数据类型非常重要,它决定了该列可以存储什么样的数据以及如何存储。PostgreSQL 支持丰富的数据类型:

  • 数值类型:

    • SMALLINT, INTEGER (或 INT), BIGINT: 存储整数,区别在于存储范围。
    • SERIAL, BIGSERIAL: 自动递增的整数类型,常用于主键(Primary Key)。相当于创建一个序列(sequence)并将其默认值设为序列的下一个值,并添加 NOT NULL 约束。
    • REAL, DOUBLE PRECISION: 存储浮点数。
    • NUMERIC(p, s)DECIMAL(p, s): 精确数值类型,p 是总位数,s 是小数点后的位数。适用于货币等需要高精度计算的场景。
  • 字符类型:

    • VARCHAR(n): 可变长度字符串,最大长度 n
    • CHAR(n): 定长字符串,长度固定为 n
    • TEXT: 可变长度字符串,没有最大长度限制。
  • 日期/时间类型:

    • DATE: 存储日期 (年、月、日)。
    • TIME: 存储时间 (时、分、秒)。
    • TIMESTAMP: 存储日期和时间。
    • TIMESTAMP WITH TIME ZONE (或 TIMESTAMPTZ): 存储带时区的日期和时间。
  • 布尔类型:

    • BOOLEAN (或 BOOL): 存储真/假值 (TRUE/FALSE/NULL)。
  • 其他类型:

    • UUID: 通用唯一标识符。
    • JSON, JSONB: 存储 JSON 数据,JSONB 是更高效的二进制格式。
    • ARRAY: 存储同一种数据类型的数组。
    • ENUM: 枚举类型,存储预定义的一组值。
    • GEOMETRY, GEOGRAPHY: 存储地理空间数据 (需要 PostGIS 扩展)。

选择合适的数据类型可以节省存储空间,提高查询效率,并确保数据的有效性。

4.3 SQL 语言简介

SQL (Structured Query Language,结构化查询语言) 是用于管理关系型数据库的标准语言。它分为几个主要部分:

  • DDL (Data Definition Language,数据定义语言): 用于定义数据库结构,如创建、修改、删除数据库对象(库、表、索引等)。
    • CREATE DATABASE
    • CREATE TABLE
    • ALTER TABLE
    • DROP TABLE
    • CREATE INDEX
  • DML (Data Manipulation Language,数据操纵语言): 用于操作数据库中的数据,如插入、更新、删除、查询数据。
    • INSERT INTO
    • SELECT FROM
    • UPDATE SET
    • DELETE FROM
  • DCL (Data Control Language,数据控制语言): 用于管理用户权限。
    • GRANT
    • REVOKE
  • TCL (Transaction Control Language,事务控制语言): 用于管理事务。
    • BEGIN / START TRANSACTION
    • COMMIT
    • ROLLBACK

作为新手,我们将重点学习 DDL 和 DML 中最常用的语句。

第 5 章:核心 SQL 操作 (DML & DDL 基础)

现在,让我们通过实际操作来学习如何创建表、插入数据、查询数据、更新数据和删除数据。

假设我们要创建一个简单的用户管理系统,需要存储用户的信息。

5.1 创建数据库

首先,我们创建一个新的数据库来存放我们的表。在 psql 或 pgAdmin 的 Query Tool 中执行:

sql
CREATE DATABASE user_db;

如果你在 pgAdmin 中执行,可能需要刷新服务器列表才能看到新创建的数据库。接下来,连接到这个新数据库(在 psql 中使用 \c user_db;,在 pgAdmin 中双击数据库名)。

5.2 创建表 (CREATE TABLE)

接下来,在 user_db 数据库中创建一个名为 users 的表,用于存储用户信息。

sql
CREATE TABLE users (
user_id SERIAL PRIMARY KEY, -- 用户ID,自动递增,主键
username VARCHAR(50) UNIQUE NOT NULL, -- 用户名,字符串,最长50,唯一且非空
email VARCHAR(100) UNIQUE NOT NULL, -- 邮箱,字符串,最长100,唯一且非空
registration_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 注册日期,带时间戳,默认为当前时间
is_active BOOLEAN DEFAULT TRUE -- 是否活跃,布尔类型,默认为真
);

解释一下上面的语句:

  • CREATE TABLE users: 创建一个名为 users 的新表。
  • 括号内部定义了表的列:
    • user_id SERIAL PRIMARY KEY: 定义一个名为 user_id 的列。SERIAL 是 PostgreSQL 的一种伪类型,它会自动创建一个序列,并为该列设置 NOT NULL 约束和默认值为序列的下一个值,同时将其指定为 PRIMARY KEY(主键)。主键用于唯一标识表中的每一行,它必须是唯一的且非空。
    • username VARCHAR(50) UNIQUE NOT NULL: 定义 username 列,类型是变长字符串,最大长度 50。UNIQUE 约束保证 username 在整个表中是唯一的,NOT NULL 约束保证该列不能为 NULL 值。
    • email VARCHAR(100) UNIQUE NOT NULL: 定义 email 列,与 username 类似,但最大长度 100。
    • registration_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP: 定义 registration_date 列,类型为时间戳。DEFAULT CURRENT_TIMESTAMP 指定如果插入数据时没有为这一列提供值,将自动使用当前的数据库服务器时间。
    • is_active BOOLEAN DEFAULT TRUE: 定义 is_active 列,类型为布尔值。DEFAULT TRUE 指定如果插入数据时没有提供值,默认为 TRUE

执行上述 CREATE TABLE 语句后,你可以使用 \dt (在 psql 中) 或在 pgAdmin 中刷新表列表来查看新创建的 users 表。使用 \d users (在 psql 中) 可以查看表的详细结构。

5.3 插入数据 (INSERT INTO)

现在我们向 users 表中插入一些数据。

插入一条完整的记录,指定所有列的值(除了自动生成的 user_id):

sql
INSERT INTO users (username, email)
VALUES ('alice', '[email protected]');

这里我们只指定了 usernameemail,因为 user_idSERIAL 类型会自动生成,registration_dateis_active 有默认值。

插入另一条记录,这次指定所有列的值(包括有默认值的列):

sql
INSERT INTO users (username, email, registration_date, is_active)
VALUES ('bob', '[email protected]', '2023-01-15 10:00:00', FALSE);

如果你要插入所有列(除了自动生成的 SERIAL 列),可以省略列名列表:

sql
-- 假设表中除了user_id之外只有 username, email, registration_date, is_active 这四列
-- 这种写法要求VALUES中的值顺序和类型与CREATE TABLE时定义的列顺序一致,不推荐用于生产环境,容易出错
-- 推荐始终指定列名列表
INSERT INTO users
VALUES (DEFAULT, 'charlie', '[email protected]', DEFAULT, DEFAULT); -- DEFAULT用于显式使用列的默认值

注意:DEFAULT 关键字可以用于显式地让数据库使用列的默认值,特别是对于 SERIAL 或带有 DEFAULT 子句的列。

插入多条记录:

sql
INSERT INTO users (username, email)
VALUES
('david', '[email protected]'),
('eve', '[email protected]');

5.4 查询数据 (SELECT)

SELECT 语句是使用最频繁的语句,用于从数据库中检索数据。

  • 查询所有列和所有行:

    sql
    SELECT * FROM users;

    这将返回 users 表中的所有列和所有行。

  • 查询指定列的所有行:

    sql
    SELECT username, email FROM users;

    这将只返回 usernameemail 列。

  • 查询指定列和符合条件的行 (WHERE 子句):
    WHERE 子句用于过滤查询结果,只返回满足特定条件的行。

    “`sql
    — 查询用户名为 ‘alice’ 的用户
    SELECT * FROM users WHERE username = ‘alice’;

    — 查询注册日期在某个日期之后的用户
    SELECT username, registration_date FROM users WHERE registration_date > ‘2023-01-01’;

    — 查询所有活跃的用户
    SELECT username, is_active FROM users WHERE is_active = TRUE;

    — 使用 AND 和 OR 组合条件
    — 查询用户名为 ‘bob’ 且不活跃的用户
    SELECT * FROM users WHERE username = ‘bob’ AND is_active = FALSE;

    — 查询 user_id 大于 2 或用户名为 ‘eve’ 的用户
    SELECT * FROM users WHERE user_id > 2 OR username = ‘eve’;

    — 使用 LIKE 进行模糊匹配
    — 查询用户名以 ‘a’ 开头的用户
    SELECT * FROM users WHERE username LIKE ‘a%’; — % 表示任意数量的字符
    — 查询邮箱包含 ‘@example.com’ 的用户
    SELECT * FROM users WHERE email LIKE ‘%@example.com%’;
    — 查询用户名第二个字符是 ‘o’ 的用户 (_ 表示一个字符)
    SELECT * FROM users WHERE username LIKE ‘_o%’;

    — 使用 IN 查询在列表中的值
    — 查询用户名为 ‘alice’ 或 ‘david’ 的用户
    SELECT * FROM users WHERE username IN (‘alice’, ‘david’);

    — 使用 BETWEEN 查询范围内的值 (包含边界)
    — 查询 user_id 在 2 到 4 之间的用户
    SELECT * FROM users WHERE user_id BETWEEN 2 AND 4;
    “`

  • 对结果进行排序 (ORDER BY 子句):
    ORDER BY 子句用于按照一个或多个列对查询结果进行排序。默认是升序 (ASC),可以使用 DESC 指定降序。

    “`sql
    — 按用户名升序排序
    SELECT * FROM users ORDER BY username ASC;

    — 按注册日期降序排序
    SELECT * FROM users ORDER BY registration_date DESC;

    — 先按是否活跃降序,再按注册日期升序排序
    SELECT * FROM users ORDER BY is_active DESC, registration_date ASC;
    “`

  • 限制返回的行数 (LIMIT 和 OFFSET 子句):
    LIMIT 用于限制返回的最大行数,OFFSET 用于跳过前面的行(常用于分页)。

    “`sql
    — 只返回前 3 条记录
    SELECT * FROM users LIMIT 3;

    — 跳过前 3 条记录,然后返回接下来的 2 条记录 (用于第二页,每页 2 条)
    SELECT * FROM users LIMIT 2 OFFSET 3;
    “`

5.5 更新数据 (UPDATE)

UPDATE 语句用于修改表中现有记录的数据。务必小心使用 UPDATE 语句,特别是没有 WHERE 子句时,它会更新表中的所有行!

“`sql
— 更新用户名为 ‘alice’ 的邮箱地址
UPDATE users
SET email = ‘[email protected]
WHERE username = ‘alice’;

— 更新 user_id 为 2 的用户的活跃状态为 TRUE 和注册日期
UPDATE users
SET is_active = TRUE, registration_date = ‘2024-01-01 08:00:00’
WHERE user_id = 2;

— !!!! 危险操作 !!!! 更新所有用户的活跃状态为 FALSE (如果没有 WHERE 子句)
— UPDATE users SET is_active = FALSE;
— 建议在执行没有 WHERE 的 UPDATE 或 DELETE 前,先用 SELECT 确认影响范围。
“`

5.6 删除数据 (DELETE FROM)

DELETE FROM 语句用于从表中删除记录。同样,务必小心使用 DELETE FROM 语句,特别是没有 WHERE 子句时,它会删除表中的所有行!

“`sql
— 删除用户名为 ‘bob’ 的用户记录
DELETE FROM users
WHERE username = ‘bob’;

— 删除所有不活跃的用户记录
DELETE FROM users
WHERE is_active = FALSE;

— !!!! 危险操作 !!!! 删除表中的所有记录 (如果没有 WHERE 子句)
— DELETE FROM users;
— 要清空整个表并重置 SERIAL 计数器,可以使用 TRUNCATE TABLE users RESTART IDENTITY;
“`

5.7 删除表 (DROP TABLE)

如果你不再需要某个表,可以使用 DROP TABLE 语句将其删除。注意:这是一个不可逆的操作,将永久删除表及其包含的所有数据!

sql
DROP TABLE users;

第 6 章:更进一步:表之间的关系 (JOIN)

在关系型数据库中,数据通常分散在多个相关的表中,而不是一个巨大的表中,这被称为规范化 (Normalization),有助于减少数据冗余、提高数据一致性。通过定义表之间的关系,我们可以使用 JOIN 操作将来自不同表的数据组合起来。

假设除了用户表,我们还有一个城市表,我们想知道每个用户所在的城市。

6.1 创建城市表

“`sql
CREATE TABLE cities (
city_id SERIAL PRIMARY KEY,
city_name VARCHAR(100) UNIQUE NOT NULL
);

INSERT INTO cities (city_name) VALUES (‘New York’), (‘London’), (‘Tokyo’), (‘Paris’);
“`

6.2 修改用户表以关联城市

我们需要在 users 表中添加一个列来存储用户所在的城市 ID,并建立与 cities 表的关联。

“`sql
— 添加 city_id 列
ALTER TABLE users
ADD COLUMN city_id INTEGER;

— 创建外键约束,关联 users 表的 city_id 列和 cities 表的 city_id 列
— 这会保证 users 表中的 city_id 值必须是 cities 表中已存在的 city_id 值 (或者为 NULL)
ALTER TABLE users
ADD CONSTRAINT fk_user_city
FOREIGN KEY (city_id) REFERENCES cities (city_id);
“`

解释:
* ALTER TABLE users ADD COLUMN city_id INTEGER;: 在 users 表中添加一个名为 city_id 的整数列。
* ALTER TABLE users ADD CONSTRAINT fk_user_city FOREIGN KEY (city_id) REFERENCES cities (city_id);: 添加一个名为 fk_user_city 的外键约束。它指定 users 表的 city_id 列是引用 cities 表的 city_id 列的外键。这是一种数据完整性约束。

6.3 更新用户数据,指定城市

现在我们可以更新用户记录,为他们指定所在的城市 ID。首先,我们需要知道城市的 ID。可以查询 cities 表:

sql
SELECT * FROM cities;
-- 假设查询结果是:
-- city_id | city_name
-- --------+-----------
-- 1 | New York
-- 2 | London
-- 3 | Tokyo
-- 4 | Paris

现在更新 users 表:

sql
UPDATE users SET city_id = 1 WHERE username = 'alice'; -- Alice住在New York
UPDATE users SET city_id = 2 WHERE username = 'charlie'; -- Charlie住在London
-- David和Eve暂时没有指定城市 (city_id 保持 NULL)

6.4 使用 JOIN 查询关联数据

现在我们可以使用 JOIN 来查询用户的同时显示他们所在的城市名称。

sql
SELECT
u.username,
u.email,
c.city_name
FROM
users u -- 给 users 表起别名 u
INNER JOIN
cities c ON u.city_id = c.city_id; -- 给 cities 表起别名 c, 使用 ON 指定关联条件

解释:
* SELECT u.username, u.email, c.city_name: 选择用户表 (u) 的用户名和邮箱,以及城市表 (c) 的城市名称。使用 表别名.列名 的格式来消除列名可能存在的歧义。
* FROM users u: 指定从 users 表查询,并给它一个别名 u
* INNER JOIN cities c ON u.city_id = c.city_id: 使用 INNER JOINusers 表与 cities 表连接起来。ON u.city_id = c.city_id 指定了连接的条件:只有当 users 表的 city_idcities 表的 city_id 相等时,才将这两行的信息合并为一条结果记录。

执行上述 INNER JOIN 查询,你会看到 alicecharlie 的用户名、邮箱以及他们对应的城市名。那些 city_idNULL 的用户 (david, eve) 不会出现在结果中,因为 INNER JOIN 只返回在两个表中都存在匹配的行。

如果想包含所有用户,即使他们没有指定城市,可以使用 LEFT JOIN

sql
SELECT
u.username,
u.email,
c.city_name
FROM
users u
LEFT JOIN
cities c ON u.city_id = c.city_id;

解释:LEFT JOIN (或 LEFT OUTER JOIN) 会返回左表 (users) 中的所有行,以及右表 (cities) 中匹配的行。如果左表中的某行在右表中没有匹配,那么右表对应的列将显示 NULL

执行 LEFT JOIN 查询,你会看到所有用户的用户名、邮箱,以及他们对应的城市名(如果指定了),对于未指定城市的用户,city_name 列将显示 NULL

RIGHT JOINFULL OUTER JOIN 也是类似的连接类型,但 INNER JOINLEFT JOIN 是最常用的。

第 7 章:超越基础

你已经掌握了 PostgreSQL 的安装、连接以及基本的数据库和 SQL 操作。这为你进一步深入学习奠定了坚实的基础。以下是一些可以继续探索的方向:

  • 聚合函数 (Aggregate Functions): COUNT(), SUM(), AVG(), MIN(), MAX() 等,用于对一组值进行计算。通常与 GROUP BY 子句一起使用,按某个列分组后进行聚合计算。
  • 索引 (Indexes): 类似书籍的目录,可以极大地加快数据的检索速度,尤其是在大型表上。
  • 事务 (Transactions): 确保一系列数据库操作要么全部成功,要么全部失败,保持数据的一致性。
  • 视图 (Views): 虚拟的表,基于一个 SELECT 查询的结果。可以简化复杂的查询,或限制用户对底层数据的访问。
  • 存储过程和函数 (Stored Procedures and Functions): 将一系列 SQL 语句封装起来,可以提高效率和安全性。
  • 触发器 (Triggers): 在特定的数据库事件(如 INSERT, UPDATE, DELETE)发生时自动执行的函数。
  • 数据库设计 (Database Design / Normalization): 学习如何合理地设计数据库结构,以减少冗余和提高效率。
  • 用户和权限管理 (User and Privilege Management): 如何创建不同的用户并赋予他们不同的操作权限,保障数据安全。
  • 备份与恢复 (Backup and Restore): 如何定期备份数据库以防数据丢失,以及如何在需要时恢复数据。
  • 性能优化 (Performance Tuning): 学习如何分析和优化慢查询,提高数据库整体性能。
  • PostgreSQL 扩展 (Extensions): PostgreSQL 拥有丰富的扩展生态,如 PostGIS (地理空间数据)、TimescaleDB (时序数据) 等。

第 8 章:实践与资源

学习数据库最好的方式就是动手实践。

  • 多练习 SQL 语句: 尝试使用你学过的语句创建不同结构的表,插入各种数据,并进行各种查询、更新和删除操作。
  • 尝试构建一个小项目: 比如一个简单的博客系统、一个商品目录,用 PostgreSQL 存储数据,这将帮助你更好地理解如何将数据库应用到实际场景中。
  • 阅读官方文档: PostgreSQL 官方文档非常详细和准确,是学习和解决问题的宝库。虽然刚开始可能有些难度,但它是你深入学习的最佳资源。
  • 参与社区: 加入 PostgreSQL 相关的在线社区、论坛或邮件列表,与其他用户交流,提问和分享经验。

结论

恭喜你!你已经完成了 PostgreSQL 新手入门的学习。你现在应该对关系型数据库、PostgreSQL 以及基本的 SQL 操作有了清晰的认识,并且掌握了如何安装、连接和进行数据操作。

这仅仅是 PostgreSQL 强大功能的冰山一角。但有了这些基础,你已经具备了进一步学习和探索的能力。

数据库是软件开发中不可或缺的一部分,掌握 PostgreSQL 将极大地增强你的技能树。保持好奇心,持续实践,祝你在数据库世界的旅程愉快!

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部