第 18 章:修改表结构 (ALTER TABLE) - PostgreSQL入门

在理想世界里,我们会在项目开始时就完美地设计好所有数据表,然后一劳永逸。但现实是,需求总在不断变化。


“我们需要给用户增加一个手机号字段。”
“订单表需要记录发货状态。”
“我们决定
username 不再需要唯一了。”

当遇到这些情况时,我们总不能删掉原来的表再重建一个吧?(那数据就全丢了!)这时,ALTER TABLE 命令就成了我们的救星。

ALTER TABLE 是一个功能极其丰富的命令集,它允许我们在不丢失数据的前提下,对现有表的结构进行各种“外科手术”:添加、删除、修改列,甚至是添加和删除约束。

警告 :在生产环境的数据库上执行 ALTER TABLE 是一个高风险操作。根据操作的类型和表的大小,它可能会锁定表,导致应用暂时无法访问,甚至可能需要很长的执行时间。在执行前,请务必了解其影响,并最好在业务低峰期进行。


准备工作

我们继续使用上一章创建的 users 表。

-- 回顾一下 users 表的结构
-- \d users (在 psql 中)
-- Table "public.users"
--   Column  |          Type          | Collation | Nullable |              Default
-- ----------+------------------------+-----------+----------+------------------------------------
--  user_id  | integer                |           | not null | nextval('users_user_id_seq'::regclass)
--  username | character varying(50)  |           | not null |
--  email    | character varying(100) |           | not null |
--  age      | integer                |           |          |
-- Indexes:
--     "users_pkey" PRIMARY KEY, btree (user_id)
--     "users_email_key" UNIQUE CONSTRAINT, btree (email)
--     "users_username_key" UNIQUE CONSTRAINT, btree (username)
-- Check constraints:
--     "users_age_check" CHECK (age >= 18)

18.1 添加、删除、修改列

添加新列 (ADD COLUMN)

最常见的需求:给 users 表增加一个 phone_number 字段。

ALTER TABLE users
ADD COLUMN phone_number VARCHAR(20);

执行后,users 表的每一行都会多出一个 phone_number 列,其默认值为 NULL

你也可以在添加列的同时,为它指定一个默认值 (DEFAULT)。这对于那些已经有数据的表非常有用。

ALTER TABLE users
ADD COLUMN registration_date DATE DEFAULT CURRENT_DATE;

这条命令会添加一个 registration_date 列,并且表中所有现有行的该字段都会被自动填充为今天的日期。

删除列 (DROP COLUMN)

这是一个危险操作! 删除列会永久地移除该列及其所有数据,且通常无法恢复。

假设我们后来觉得 age 这个字段不合适,决定去掉它。

ALTER TABLE users
DROP COLUMN age;

执行后,age 列以及与之关联的 CHECK (age >= 18) 约束都会被一并删除。

修改列 (ALTER COLUMN)

修改列可以做很多事,比如更改数据类型、设置/删除默认值、添加/删除 NOT NULL 约束。

1. 更改数据类型 (TYPE)
假设我们发现 phone_numberVARCHAR(20) 不够用,想改成 VARCHAR(30)

ALTER TABLE users
ALTER COLUMN phone_number TYPE VARCHAR(30);

注意:不是所有类型之间都能随意转换的。比如,将一个包含文本的 VARCHAR 列转成 INT 列通常会失败。

2. 添加 NOT NULL 约束
我们决定 phone_number 必须是必填项。

-- 首先,确保所有现有行的 phone_number 都不是 NULL
UPDATE users SET phone_number = 'N/A' WHERE phone_number IS NULL;

-- 然后,添加 NOT NULL 约束
ALTER TABLE users
ALTER COLUMN phone_number SET NOT NULL;

如果表里已经有 NULL 值,直接添加 NOT NULL 会失败。

3. 删除 NOT NULL 约束

ALTER TABLE users
ALTER COLUMN phone_number DROP NOT NULL;

4. 设置/删除默认值 (DEFAULT)

-- 设置默认值
ALTER TABLE users
ALTER COLUMN age SET DEFAULT 18;

-- 删除默认值
ALTER TABLE users
ALTER COLUMN age DROP DEFAULT;

18.2 添加和删除约束

我们也可以在表创建后,动态地添加和删除约束。

添加约束 (ADD CONSTRAINT)

给约束起一个明确的名字是一个非常好的习惯。

1. 添加 UNIQUE 约束
假设我们想给 phone_number 也加上唯一约束。

ALTER TABLE users
ADD CONSTRAINT unique_phone_number UNIQUE (phone_number);
  • unique_phone_number 是我们给这个约束起的名字。

2. 添加 CHECK 约束

ALTER TABLE users
ADD CONSTRAINT check_username_length CHECK (length(username) > 3);

3. 添加 FOREIGN KEY 约束

ALTER TABLE orders
ADD CONSTRAINT fk_orders_users FOREIGN KEY (user_id) REFERENCES users(user_id);

删除约束 (DROP CONSTRAINT)

删除约束就需要用到我们给它起的名字了。

-- 删除我们刚刚创建的唯一约束
ALTER TABLE users
DROP CONSTRAINT unique_phone_number;

-- 删除主键约束(不常用,但可以做到)
-- ALTER TABLE users DROP CONSTRAINT users_pkey;

18.3 重命名表和列

重命名列 (RENAME COLUMN)

ALTER TABLE users
RENAME COLUMN email TO email_address;

重命名表 (RENAME TO)

ALTER TABLE users
RENAME TO app_users;

本章小结

你已经掌握了像一个经验丰富的数据库管理员(DBA)一样,对数据库结构进行维护和演进的技能。

  • 我们学会了用 ADD COLUMN, DROP COLUMN, ALTER COLUMN 来灵活地管理表的列
  • 学会了用 ADD CONSTRAINTDROP CONSTRAINT 来动态地调整表的规则
  • 还学会了如何重命名表和列。

ALTER TABLE 是一个强大但需要谨慎使用的工具。理解它的能力和潜在风险,是保证数据库能够随着业务发展而平滑演进的关键。

在下一章,我们将学习一个非常有趣的概念——视图 (Views)。它像一个虚拟的、只读的表,可以用来简化复杂的查询、封装业务逻辑,并提供一个安全的数据访问层。准备好学习如何创建你自己的“数据窗口”了吗?我们下一章见!

原文链接:,转发请注明来源!