安装 PostgreSQL
PostgreSQL 是一个功能强大的开源对象关系数据库系统。它经过数十年的积极开发和经过验证的架构,使其在可靠性、数据完整性和正确性方面赢得了良好的声誉。而其天生支持异步操作的特性,在高并发场景中倍受欢迎。同时,它的扩展性极强,只要你有能力,你可以使用任何你熟悉的其它开发语言来编写 PostgreSQL 脚本,比如:Rust、Python 等。PostgreSQL 对象
本章将介绍 PostgreSQL 常见的服务器和数据库对象。示例数据库
本章将介绍示例数据库,以便后续的演示。同时,你将学习到如何将已存在的数据导入到 PostgreSQL 中。基础 SELECT
本章将讨论如何使用简单的 `SELECT` 语句从 PostgreSQL 查询数据。PostgreSQL 的 `SELECT` 语句有诸多独特的特性,让我们一起感受一下。WHERE 子句
本章我们将学习 `WHERE` 子句,它不但能用于 `SELECT` 过滤查询结果,还能用于其它语句。LIMIT、OFFSET 和 FETCH 子句
本章我们学习 `LIMIT` 、`OFFSET` 和 `FETCH` 子句。和 `LIMIT` 一样,`FETCH` 也是为了限定返回的行数,但你不知道的是,`FETCH` 才是 SQL 标准,而 `LIMIT` 不是。LIKE 和 ILIKE
前面章节提过,在 PostgreSQL 中,`LIKE` 是区分大小写的。如果要像其它数据库那样不区分大小写,需要使用 `ILIKE`。PostgreSQL 还为它们提供了等价的运算符。连接
本章将讨论 PostgreSQL 的各种连接:内连接、左外连接、右外连接、交叉连接、自然连接、自连接和完全外连接。值得一提的是,哪怕到了 MySQL 8,MySQL 依然不支持完全外连接。分组
本章将讨论 PostgreSQL 的 `GROUP BY` 子句:将`SELECT` 语句返回的结果进行分组;对于每个分组,可以使用聚合函数。同时讨论与之相关的 `HAVING`、`CUBE`、`ROLLUP` 等。联合查询(并集)、交集查询及差集查询
本章将讨论 `UNION`:联合(并集)查询、`INTERSECT `:交集查询和`EXCEPT`:差集查询。子查询
本章我们将讨论如何使用 PostgreSQL 子查询来构建复杂的查询。同时会学习 `IN`、`EXISTS`、`ANY`、`SOME`、`ALL` 等操作。插入数据
本章将讨论如何使用 `INSERT` 向 PostgreSQL 中插入新行。同时介绍如何通过`REGURNING`子句返回最新插入行的ID以及批量插入数据的方法。修改数据
本章将讨论如何使用 `UPDATE` 语句修改 PostgreSQL 数据,以及配合 `RETURNING` 子句在修改数据的同时,返回修改后的内容。最后,还将介绍 `UPDATE JOIN`:根据另一张表中的数据进行修改。删除数据
本章将讨论如何使用 `DELETE` 语句删除 PostgreSQL 数据,以及配合 `RETURNING` 子句在删除数据的同时,返回已删除的内容。最后,还将介绍 `DELETE JOIN`:根据另一张表中的数据进行删除。插入或更新数据
在关系型数据库中,术语`upsert`称为合并:当插入数据时,如果数据已存在则进行更新,否则插入新行。PostgreSQL 使用 `INSERT ON CONFLICT` 实现这一功能。基础数据类型
本章我们讨论 PostgreSQL 的基本数据类型:布尔型、字符型、数值型和日期时间型。这些类型与其它数据库有着很多不同,让我们一起深入细节进行了解。表
本章将讨论和表相关的知识,包括:创建表、修改表、清空(截断)表和删除表。约束
本章将讨论 PostgreSQL 的约束,包括:主键约束、外键约束、唯一约束、非空约束、 CHECK 约束。条件表达式和运算符
本章将讨论 PostgreSQL 条件表达式和运算符,包括:使用 `CASE` 构造条件查询、使用 `COALESCE` 过滤非空参数、使用 `NULLIF` 处理 `NULL` 值以及使用 `CAST` 进行数据类型转换。视图
本章我们将讨论视图:创建、修改、删除视图。为高级篇的物化视图、递归视图等打好基础。性能分析
PostgreSQL 提供了 `EXPLAIN` 语句,它可以用来分析 SQL 的执行情况。本章将对其进行讨论。索引
PostgreSQL 索引是增强数据库查询性能的有效工具。然而,索引增加了数据库系统的写入和存储开销。因此,正确使用它们非常重要。本章我们将讨论如何使用索引。角色与权限
本章介绍角色与权限。PostgreSQL 使用角色来表示用户账号,而不是其它数据库那样使用用户概念。客户端鉴权
本章将讨论 PostgreSQL 客户端鉴权。回到之前安装 PostgreSQL 时的一个问题,为什么在本地登录 PostgreSQL 时,不需要输入密码?本章将回答这个问题。事务
本章将讨论如何使用 `BEGIN` 、 `COMMIT` 和 `ROLLBACK` 语句处理 PostgreSQL 事务。备份与还原
本章将介绍备份和还原 PostgreSQL 数据库。常用函数
本章对 PostgreSQL 常用函数进行汇总,包括:聚合函数、日期时间函数、字符串函数和数学函数。对于窗口函数,我们将在高级篇进行介绍。
表
- 510
- 2023-07-31 06:02:18
本章将讨论和表相关的知识,包括:创建表、修改表、清空(截断)表和删除表。
使用CREATE TABLE
创建新表,语法如下:
CREATE TABLE [IF NOT EXISTS] 表名(
字段1 数据类型 [字段约束] [DEFAULT 默认值],
字段2 数据类型 [字段约束] [DEFAULT 默认值],
...,
[表约束]
);
- 首先,在
CREATE TABLE
后面指定表名 - 其次,如果欲创建的表已经存在,则会报错。
IF NOT EXISTS
选项用于指定当同名的表不存在时才创建,以避免报错。 - 第三,以逗号分隔,指定要表的字段
- 每个字段由:
字段名
、数据类型
、字段约束
和默认值
构成 - 关于
约束
,我们会在后续章节进行详细说明,它是可选的 - 你可以给字段设置默认值,语法是
DEFAULT 默认值
。当然,不同的数据类型其默认值也不同,你指定的默认值要和数据类型相兼容。它也是可选的。
- 每个字段由:
- 最后,你可以指定表约束,它也是可选的。很多约束可以在字段中定义,但有些约束只能在表约束里指定,比如复合约束。
- 每个字段由:
字段名
、数据类型
、字段约束
和默认值
构成 - 关于
约束
,我们会在后续章节进行详细说明,它是可选的 - 你可以给字段设置默认值,语法是
DEFAULT 默认值
。当然,不同的数据类型其默认值也不同,你指定的默认值要和数据类型相兼容。它也是可选的。
关于约束的详细内容我们会在后续章节详细进行说明,这里大概总结一下 PostgreSQL 的约束:
NOT NULL
:确保字段的值不能为NULL
UNIQUE
:确保该字段的值,在本张表中是唯一的PRIMARY KEY
:主键约束- 一张表只有有一个主键
- 主键约束自动拥有了
NOT NULL
加上UNIQUE
约束
CHECK
:确保数据必须满足条件,这个条件是一个布尔表达式FOREIGN KEY
:外键约束- 确保字段的值存在于另一张表中
- 一张表可有多个外键约束
- 表约束和字段约束类似,通常用于指定多个字段组成的复合约束
- 一张表只有有一个主键
- 主键约束自动拥有了
NOT NULL
加上UNIQUE
约束
- 确保字段的值存在于另一张表中
- 一张表可有多个外键约束
创建表示例
我们将创建一张名为 accounts
(账户) 的表,结构如下:
SQL 如下:
CREATE TABLE accounts (
user_id serial PRIMARY KEY,
username VARCHAR ( 50 ) UNIQUE NOT NULL,
password VARCHAR ( 50 ) NOT NULL,
email VARCHAR ( 255 ) UNIQUE NOT NULL,
created_on TIMESTAMP NOT NULL,
last_login TIMESTAMP
);
然后我们创建 roles
(角色)表:
字段 | 数据类型 | 约束 |
---|---|---|
role_id | serial | PRIMARY KEY |
role_name | VARCHAR(255) | UNIQUE 和NOT NULL |
SQL 如下:
CREATE TABLE roles(
role_id serial PRIMARY KEY,
role_name VARCHAR (255) UNIQUE NOT NULL
);
接下来创建 account_roles
(账户-角色)表:
字段 | 数据类型 | 约束 |
---|---|---|
user_id | INTEGER | NOT NULL 及FOREIGN KEY |
role_id | INTEGER | NOT NULL 及FOREIGN KEY |
grant_date | TIMESTAMP | (无) |
(表约束) | user_id 和role_id 构成的复合 PRIMARY KEY 约束 |
SQL 如下:
CREATE TABLE account_roles (
user_id INT NOT NULL,
role_id INT NOT NULL,
grant_date TIMESTAMP,
PRIMARY KEY (user_id, role_id),
FOREIGN KEY (role_id)
REFERENCES roles (role_id),
FOREIGN KEY (user_id)
REFERENCES accounts (user_id)
);
- 它的主键由
user_id
和role_id
构成的复合约束,像这种复合约束无法在某个字段上指定,所以通常在表约束指定:PRIMARY KEY (user_id, role_id)
- 因为
role_id
是一个引用用roles
表中role_id
的外键,所以,使用FOREIGN KEY (role_id) REFERENCES roles (role_id)
设置外键约束的同时,指定所引用的目标表和字段 user_id
和role_id
相同道理
基于查询结果创建新表
SELECT INTO
语句允许基于查询结果来创建新表,语法如下:
SELECT
select_list
INTO [ TEMPORARY | TEMP | UNLOGGED ] [ TABLE ] new_table_name
FROM
table_name
WHERE
search_condition;
示例:查询出评级为 R
,且租赁期限在 5
天的结果,并基于此结果创建 film_r
新表:
SELECT
film_id,
title,
rental_rate
INTO TABLE film_r
FROM
film
WHERE
rating = 'R'
AND rental_duration = 5
ORDER BY
title;
基于查询结果创建新表(2)
通过 CREATE TABLE AS
也可以基于查询结果创建新表:
CREATE TABLE new_table_name
AS query;
示例:
CREATE TABLE action_film AS
SELECT
film_id,
title,
release_year,
length,
rating
FROM
film
INNER JOIN film_category USING (film_id)
WHERE
category_id = 1;
修改表
ADD COLUMN
: 添加字段DROP COLUMN
:删除字段RENAME COLUMN
:重命名字段ALTER COLUMN
:修改字段ADD CONSTRAINT
:添加约束RENAME TO
:修改表名ADD CHECK
:添加CHECK
约束
示例
示例数据:
DROP TABLE IF EXISTS links;
CREATE TABLE links (
link_id serial PRIMARY KEY,
title VARCHAR (512) NOT NULL,
url VARCHAR (1024) NOT NULL
);
-- 添加字段 active,数据类型为 boolean
ALTER TABLE links
ADD COLUMN active boolean;
-- 删除字段 active
ALTER TABLE links
DROP COLUMN active;
-- 将字段 title 重命名为 link_title
ALTER TABLE links
RENAME COLUMN title TO link_title;
-- 添加字段 target,数据类型为 VARCHAR(10)
ALTER TABLE links
ADD COLUMN target VARCHAR(10);
-- 修改字段 target,为其加上默认值
ALTER TABLE links
ALTER COLUMN target
SET DEFAULT '_blank';
-- 为 target 字段添加 CHECK 约束
ALTER TABLE links
ADD CHECK (target IN ('_self', '_blank', '_parent', '_top'));
-- 为 url 字段添加 UNIQUE 约束
ALTER TABLE links
ADD CONSTRAINT unique_url UNIQUE ( url );
-- 修改字段 target,数据类型为 VARCHAR(20)
ALTER TABLE links
ALTER COLUMN target VARCHAR(20);
-- 将 links 表重命名为 urls
ALTER TABLE links
RENAME TO urls;
使用 DROP TABLE
语句可以删除指定的表,语法:
DROP TABLE [IF EXISTS] 表名
[CASCADE | RESTRICT];
IF EXISTS
:如果删除的表不存在,PostgreSQL 会报错。加上IF EXISTS
:如果表存在则删除,如果不存在则什么都不做CASCADE
:删除的指定表的同时,出删除依赖该表的其它对象。RESTRICT
:如果有任何其它对象依赖指定表,则无法删除指定表。这是默认值。
清空(截断)表
TRUNCATE TABLE
用于清空表。注意它和删除表DROP TABLE
的区别:
- 它的效率高于删除表
- 它只是清空表的数据,表本身还在;删除表的操作不但把数据清空,连表本身也一起删除了
它和 DELETE FROM 表名
的区别:
- 它的效率高于
DELETE
- 它不会扫描表,而
DELETE
会对表里的数据做扫描 - 它可以重置序列(如果有的话),而
DELETE
不行
语法:
TRUNCATE TABLE 表名
RESTART IDENTITY;
RESTART IDENTITY
:清空表的同时,重置相关联的系列