搜狐体育手机版
1.33MB · 2025-12-17
在开始创建数据库和表之前,我们需要先理解 PostgreSQL 的数据组织层级——这是后续操作的基础。PostgreSQL 用“集群-数据库-模式-表”的层级结构管理数据,就像一个“仓库-房间-货架-盒子”的模型:
ecommerce数据库和博客系统的blog数据库互不干扰)。public)。我们可以用流程图直观展示这种关系:
graph TD
A[PostgreSQL 集群] --> B[数据库1: ecommerce]
A --> C[数据库2: blog]
B --> D[模式1: public]
B --> E[模式2: admin]
D --> F[表1: users]
D --> G[表2: orders]
E --> H[表3: products]
数据库是存储表的容器,创建数据库有命令行工具和SQL语句两种方式,我们逐一讲解。
createdb 命令行工具创建createdb 是 PostgreSQL 自带的命令行工具,适合快速创建数据库。语法如下:
createdb [选项] 数据库名
常见选项:
-h:指定数据库主机(默认localhost);-p:指定端口(默认5432);-U:指定连接用户(默认当前系统用户);-O:指定数据库所有者。示例:创建一个名为ecommerce的数据库,所有者为postgres用户:
createdb -U postgres ecommerce
CREATE DATABASE SQL 语句创建如果已经通过psql或其他客户端连接到 PostgreSQL,可以用 SQL 语句创建数据库,灵活性更高。语法如下:
CREATE DATABASE 数据库名
[WITH 参数1 = 值1 参数2 = 值2 ...];
常用参数:
OWNER:数据库所有者(默认当前用户);ENCODING:字符编码(推荐UTF8,支持中文);LC_COLLATE:排序规则(比如en_US.utf8或zh_CN.utf8);TEMPLATE:基于哪个模板创建(默认template1)。示例:创建一个支持中文的电商数据库:
CREATE DATABASE ecommerce
WITH
OWNER = postgres
ENCODING = 'UTF8'
LC_COLLATE = 'zh_CN.utf8' -- 中文排序规则(提示:排序规则不兼容,可更换或删除)
LC_CTYPE = 'zh_CN.utf8' -- 中文字符分类(提示:排序规则不兼容,可更换或删除)
TABLESPACE = pg_default -- 表空间(默认即可)
CONNECTION LIMIT = -1; -- 无连接数限制
查询当前数据库支持的中文排序规则:
SELECT collname FROM pg_collation WHERE collname LIKE 'zh%';
用psql连接到 PostgreSQL,输入l命令(List Databases),如果看到ecommerce出现在列表中,说明创建成功:
psql -U postgres
postgres=# l
表是存储数据的核心对象,创建表需要定义列名、数据类型和约束(确保数据的完整性)。
创建表的 SQL 语句是CREATE TABLE,基本语法:
CREATE TABLE 表名 (
列名1 数据类型 [约束],
列名2 数据类型 [约束],
...
[表级约束]
);
PostgreSQL 支持丰富的数据类型,常用的有:
| 类型分类 | 示例类型 | 说明 |
|---|---|---|
| 数值型 | INT(整数)、BIGINT(长整数)、NUMERIC(10,2)(精确小数,保留2位) | 存储金额、数量等 |
| 字符串型 | VARCHAR(50)(可变长度字符串,最长50)、TEXT(无长度限制) | 存储用户名、邮箱等 |
| 日期时间型 | TIMESTAMP(带时区的时间戳)、DATE(日期)、TIME(时间) | 存储下单时间、注册时间等 |
| 布尔型 | BOOLEAN | 存储状态(比如is_active表示用户是否激活) |
详细数据类型参考:PostgreSQL 数据类型文档
约束是保证数据正确性的规则,常用约束包括:
NULL;age >= 18)。我们以电商系统为例,创建users(用户表)和orders(订单表),完整流程如下:
首先用c命令切换到ecommerce数据库:
c ecommerce;
users表(用户表)users表需要存储用户的ID、用户名、邮箱、密码哈希和注册时间:
CREATE TABLE users (
user_id SERIAL PRIMARY KEY, -- SERIAL:自增整数(自动创建序列),作为主键
username VARCHAR(50) NOT NULL UNIQUE, -- 用户名:非空且唯一
email VARCHAR(100) NOT NULL UNIQUE, -- 邮箱:非空且唯一
password_hash VARCHAR(255) NOT NULL, -- 密码哈希:非空(不能存明文!)
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 注册时间:默认当前时间
);
说明:
SERIAL类型会自动创建一个序列(比如users_user_id_seq),每次插入数据时自动生成下一个ID;DEFAULT CURRENT_TIMESTAMP表示如果插入时不指定created_at,自动填充当前时间。orders表(订单表)orders表需要关联users表(通过user_id外键),并记录订单金额、时间:
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
user_id INT NOT NULL, -- 关联用户表的user_id
order_total NUMERIC(10,2) NOT NULL CHECK (order_total > 0), -- 订单金额:精确到分,且必须大于0
order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
-- 外键约束:user_id必须存在于users表的user_id中
FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE
);
关键约束说明:
CHECK (order_total > 0):确保订单金额不为0或负数;FOREIGN KEY (user_id) REFERENCES users(user_id):orders的user_id必须是users表中已有的ID;ON DELETE CASCADE:如果删除users表中的某条用户数据,orders表中关联的订单会自动删除(避免无效订单)。用d命令(List Tables)查看当前数据库的表:
d
会看到users和orders表出现在列表中,说明创建成功。
创建表后,我们插入一些测试数据,验证表的约束是否生效。
INSERT INTO users (username, email, password_hash)
VALUES
('alice', '[email protected]', 'hashed_pass_123'), -- 有效数据
('bob', '[email protected]', 'hashed_pass_456'); -- 有效数据
注意:不需要指定user_id和created_at,因为SERIAL和DEFAULT会自动填充。
INSERT INTO orders (user_id, order_total)
VALUES
(1, 99.99), -- 用户1(alice)的订单,金额99.99
(2, 199.50); -- 用户2(bob)的订单,金额199.50
测试无效数据:如果尝试插入order_total = 0的订单:
INSERT INTO orders (user_id, order_total) VALUES (1, 0);
会报错:
ERROR: check constraint "orders_order_total_check" violated
这说明检查约束生效了!
用JOIN语句查询用户的订单信息:
SELECT
u.username, -- 用户名
o.order_id, -- 订单ID
o.order_total, -- 订单金额
o.order_date -- 下单时间
FROM users u
JOIN orders o ON u.user_id = o.user_id;
结果:
| username | order_id | order_total | order_date |
|---|---|---|---|
| alice | 1 | 99.99 | 2024-05-20 14:30:00 |
| bob | 2 | 199.50 | 2024-05-20 14:31:00 |
题目1:写出创建名为blog的数据库的SQL语句,要求:
admin用户;UTF8;100。
答案:CREATE DATABASE blog
WITH
OWNER = admin
ENCODING = 'UTF8'
CONNECTION LIMIT = 100;
解析:参考CREATE DATABASE的参数说明(链接)。
题目2:为什么orders表要使用FOREIGN KEY (user_id) REFERENCES users(user_id)?
答案:确保订单数据的一致性——不能存在“属于不存在的用户”的订单。如果删除users表中的某条用户数据,ON DELETE CASCADE会自动删除关联的订单(避免无效数据)。
解析:参考外键约束文档(链接)。
题目3:users表中的username字段有UNIQUE约束,插入重复的用户名会发生什么?
答案:会报错ERROR: duplicate key value violates unique constraint "users_username_key",因为违反了唯一约束。
解析:参考唯一约束文档(链接)。
在创建数据库或表时,你可能遇到以下错误,我们给出原因、解决办法和预防建议:
ERROR: database "ecommerce" already existsDROP DATABASE ecommerce;),或换一个数据库名。l命令查看现有数据库,避免重复。ERROR: syntax error at or near "SERIAL"SERIAL拼写错误(比如写成SERAL),或在不支持的位置使用(比如外键字段不能用SERIAL)。SERIAL的拼写,确保只在主键或自增字段使用。SERIAL类型文档(链接)。ERROR: insert or update on table "orders" violates foreign key constraint "orders_user_id_fkey"user_id在users表中不存在(比如插入user_id = 3,但users表中只有1和2)。user_id为存在的值。SELECT * FROM users WHERE user_id = ?检查用户是否存在。ERROR: permission denied to create databasepostgres)创建,或给用户授予CREATEDB权限:
ALTER USER myuser CREATEDB;
CREATE USER myuser WITH CREATEDB;)。以下是本文参考的 PostgreSQL 官方文档链接,建议深入阅读:
CREATE DATABASE 语句:www.postgresql.org/docs/17/sql…CREATE TABLE 语句:www.postgresql.org/docs/17/sql…