网易云音乐hd安卓版
226.97MB · 2025-09-23
在开始创建数据库和表之前,我们需要先理解 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 exists
DROP 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 database
postgres
)创建,或给用户授予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…