【PostgreSQL数据分析实战:从数据清洗到可视化全流程】1.4 数据库与表的基本操作(DDL/DML语句)

👉 点击关注不迷路

👉 点击关注不迷路

👉 点击关注不迷路


文章大纲

  • [1.4 数据库与表的基本操作(DDL/DML语句)](#1.4 数据库与表的基本操作(DDL/DML语句))
    • [1.4.1 数据库生命周期管理(DDL核心)](#1.4.1 数据库生命周期管理(DDL核心))
      • [1.4.1.1 创建数据库(CREATE DATABASE)](#1.4.1.1 创建数据库(CREATE DATABASE))
      • [1.4.1.2 查看数据库信息](#1.4.1.2 查看数据库信息)
      • [1.4.1.3 修改数据库(ALTER DATABASE)](#1.4.1.3 修改数据库(ALTER DATABASE))
      • [1.4.1.4 删除数据库(DROP DATABASE)](#1.4.1.4 删除数据库(DROP DATABASE))
    • [1.4.2 表结构定义与约束(DDL核心)](#1.4.2 表结构定义与约束(DDL核心))
      • [1.4.2.1 数据类型速查表](#1.4.2.1 数据类型速查表)
      • [1.4.2.2 创建表(CREATE TABLE)](#1.4.2.2 创建表(CREATE TABLE))
      • [1.4.2.3 修改表结构(ALTER TABLE)](#1.4.2.3 修改表结构(ALTER TABLE))
      • [1.4.2.4 删除表(DROP TABLE)](#1.4.2.4 删除表(DROP TABLE))
    • [1.4.3 数据操作语言(DML核心)](#1.4.3 数据操作语言(DML核心))
      • [1.4.3.1 插入数据(INSERT)](#1.4.3.1 插入数据(INSERT))
      • [1.4.3.2 查询数据(SELECT)](#1.4.3.2 查询数据(SELECT))
      • [1.4.3.3 更新数据(UPDATE)](#1.4.3.3 更新数据(UPDATE))
      • [1.4.3.4 删除数据(DELETE)](#1.4.3.4 删除数据(DELETE))
    • [1.4.4 事务管理与锁定机制](#1.4.4 事务管理与锁定机制)
      • [1.4.4.1 事务控制语句](#1.4.4.1 事务控制语句)
      • [1.4.4.2 锁机制](#1.4.4.2 锁机制)
    • [1.4.5 实战案例:电商订单表设计](#1.4.5 实战案例:电商订单表设计)
    • [1.4.6 最佳实践与规范](#1.4.6 最佳实践与规范)
      • [1.4.6.1 `命名规范 !!!`](#1.4.6.1 命名规范 !!!)
      • [1.4.6.2 性能优化建议](#1.4.6.2 性能优化建议)
      • [1.4.6.3 数据完整性保障](#1.4.6.3 数据完整性保障)
    • [1.4.7 常见错误与解决方案](#1.4.7 常见错误与解决方案)
      • [1.4.7.1 约束冲突处理](#1.4.7.1 约束冲突处理)
      • [1.4.7.2 大表操作技巧](#1.4.7.2 大表操作技巧)
    • [1.4.8 总结:构建健壮的数据模型](#1.4.8 总结:构建健壮的数据模型)

1.4 数据库与表的基本操作(DDL/DML语句)

1.4.1 数据库生命周期管理(DDL核心)

1.4.1.1 创建数据库(CREATE DATABASE)

sql 复制代码
-- 基础语法
-- 基础语法
CREATE DATABASE analytics_db
WITH 
    OWNER = postgres              -- 所有者
    ENCODING = 'UTF8'             -- 字符编码
--    LC_COLLATE = 'en_US.utf8'     -- 排序规则
--    LC_CTYPE = 'en_US.utf8'       -- 字符分类
    TABLESPACE = pg_default       -- 表空间
    CONNECTION LIMIT = -1         -- 最大连接数(-1无限制)
    TEMPLATE = template0;         -- 模板数据库
最佳实践
  • 使用TEMPLATE template1创建支持中文的数据库

  • 通过pg_tablespace查看可用表空间

  • 生产环境建议单独创建业务表空间:

    sql 复制代码
    CREATE TABLESPACE data_ts LOCATION '/data/pg_tablespace';

1.4.1.2 查看数据库信息

命令 说明
\lSELECT * FROM pg_database; 列出所有数据库
SELECT datname, datsize FROM pg_database; 查看数据库名称及大小
\conninfo 当前连接的数据库信息

1.4.1.3 修改数据库(ALTER DATABASE)

sql 复制代码
-- 修改所有者
ALTER DATABASE analytics_db OWNER TO data_team;

-- 限制连接数
ALTER DATABASE analytics_db CONNECTION LIMIT 100;

-- 更改参数配置(会话级生效)
ALTER DATABASE analytics_db SET work_mem = '32MB';

1.4.1.4 删除数据库(DROP DATABASE)

sql 复制代码
-- 强制删除(终止所有连接)
DROP DATABASE IF EXISTS analytics_db WITH (FORCE);

⚠️ 注意:删除前请通过SELECT * FROM pg_stat_activity WHERE datname='analytics_db';确认无活动连接

1.4.2 表结构定义与约束(DDL核心)

1.4.2.1 数据类型速查表

类型分类 常用数据类型 存储范围/特性 示例值
数值型 INT/BIGINT 4/8字节整数 100, -500
DECIMAL(p,s) 高精度十进制数(p总位数,s小数位) DECIMAL(10,2) → 1234.56
字符型 VARCHAR(n) 可变长字符串(n为最大长度) '数据分析'
TEXT 无长度限制字符串 长文本内容
日期时间 DATE 年月日(YYYY-MM-DD) '2023-12-31'
TIMESTAMP WITH TIME ZONE 带时区的时间戳 '2024-01-01 10:00:00+08'
布尔型 BOOLEAN 真/假 TRUE/FALSE
二进制 BYTEA 二进制数据(图片/文件) \xDEADBEEF
几何类型 POINT 二维坐标(x,y) POINT(10, 20)

1.4.2.2 创建表(CREATE TABLE)

sql 复制代码
CREATE TABLE departments (
    dept_id INTEGER PRIMARY KEY,
    dept_name VARCHAR(50)
);
--
 员工信息表(含约束)
CREATE TABLE employees (
    emp_id SERIAL PRIMARY KEY,          -- 自增主键
    emp_name VARCHAR(50) NOT NULL,       -- 非空约束
    email VARCHAR(100) UNIQUE,           -- 唯一约束
    hire_date DATE DEFAULT CURRENT_DATE, -- 默认值约束
    salary NUMERIC(10,2) CHECK (salary > 0), -- 检查约束
    department_id INTEGER REFERENCES departments(dept_id) -- 外键约束
);
约束类型对比
约束类型 关键字 作用 性能影响
主键 PRIMARY KEY 唯一标识记录,自动创建索引 读优化,写轻微影响
唯一 UNIQUE 确保字段值唯一 类似主键,允许NULL值
非空 NOT NULL 禁止字段为空 无索引性能影响
检查 CHECK 自定义逻辑约束 每次写入时触发检查
外键 REFERENCES 建立表间关联 级联操作需额外开销

1.4.2.3 修改表结构(ALTER TABLE)

sql 复制代码
-- 添加字段(带默认值)
ALTER TABLE employees ADD COLUMN phone VARCHAR(20) DEFAULT '未提供';

-- 修改数据类型(需重建表)
ALTER TABLE employees ALTER COLUMN salary TYPE NUMERIC(12,2);

-- 删除字段(生产环境慎用)
ALTER TABLE employees DROP COLUMN fax;

-- 添加外键(延迟约束检查)
ALTER TABLE employees 
ADD CONSTRAINT fk_dept 
FOREIGN KEY (department_id) REFERENCES departments(dept_id)
DEFERRABLE INITIALLY DEFERRED;

1.4.2.4 删除表(DROP TABLE)

sql 复制代码
-- 级联删除依赖对象
DROP TABLE IF EXISTS employees CASCADE;

-- 仅删除表结构,保留数据(PostgreSQL 12+)
TRUNCATE TABLE employees;

💡💡💡 提示:TRUNCATEDELETE FROM 效率高10-100倍,适合清空大表

💡💡💡 提示:TRUNCATEDELETE FROM 效率高10-100倍,适合清空大表

💡💡💡 提示:TRUNCATEDELETE FROM 效率高10-100倍,适合清空大表

1.4.3 数据操作语言(DML核心)

1.4.3.1 插入数据(INSERT)

sql 复制代码
-- 单条插入
INSERT INTO employees (emp_name, email, salary, department_id)
VALUES ('张三', '[email protected]', 15000, 101);

-- 批量插入(性能提升30%+)
INSERT INTO employees (emp_name, email, salary, department_id)
VALUES 
('李四', '[email protected]', 16000, 102),
('王五', '[email protected]', 17000, 101);

-- 插入并返回自增ID
INSERT INTO employees (emp_name, email, salary, department_id)
VALUES ('赵六', '[email protected]', 18000, 103)
RETURNING emp_id; -- 返回新生成的emp_id

1.4.3.2 查询数据(SELECT)

基础语法结构
sql 复制代码
SELECT 
    column1, column2, 
    CASE WHEN salary > 15000 THEN '高薪' ELSE '普通' END AS salary_level -- 条件表达式
FROM employees
WHERE hire_date >= '2023-01-01'  -- 过滤条件
  AND department_id IN (101, 102)
GROUP BY department_id           -- 分组聚合
HAVING AVG(salary) > 16000       -- 分组后过滤
ORDER BY salary DESC              -- 排序
LIMIT 10 OFFSET 20;               -- 分页(第3页,每页10条)
常用函数
函数分类 函数名 说明 示例
聚合函数 COUNT(*) / COUNT(col) 计数 COUNT(DISTINCT department_id)
SUM/AVG/MAX/MIN 数值聚合 AVG(salary)
字符串函数 CONCAT(str1, str2) 字符串拼接 CONCAT(emp_name, ' (', email, ')')
SUBSTRING(str FROM start FOR length) 子串提取 SUBSTRING(email FROM 1 FOR 5)
日期函数 AGE(timestamp) 计算时间间隔 AGE(hire_date)
DATE_TRUNC('month', date) 日期截断到月 DATE_TRUNC('quarter', now())
  • 在 PostgreSQL 中,AGE(timestamp) 是一个用于计算时间间隔的函数,主要用于获取 某个时间点与当前时间的间隔 ,或 两个时间点之间的间隔 。以下是关于该函数的详细解析:
    *

    1. 基础语法
    sql 复制代码
    AGE(timestamp)                  -- 计算 timestamp 到当前时间的间隔(等效于 AGE(now(), timestamp))
    
    AGE(end_timestamp, start_timestamp)  -- 计算两个时间点之间的间隔(end - start)
      1. 参数说明

        参数类型 描述 示例值
        timestamp 单个时间戳(可带时区 timestamptz '2020-01-01 08:00:00'
        end_timestamp 结束时间戳(必须晚于或等于开始时间) order_completed_at
        start_timestamp 开始时间戳 order_created_at
      1. 返回值类型
        返回 interval 类型,格式为 年-月-日 时:分:秒,例如:
        3 years 2 mons 10 days 03:05:15(表示 3 年 2 个月 10 天 3 小时 5 分 15 秒)。
    • 场景 1:计算单个时间点与当前时间的间隔(最常用)

    • 场景 2:计算两个时间点的间隔(如订单处理耗时)

    • 场景 3:带时区的时间戳处理(自动转换为 UTC 计算)

    • 注意事项与最佳实践

      1. 参数顺序的重要性 AGE(end, start) 必须满足 end >= start,否则会返回负数间隔(如 -1 day 00:00:00)。
      1. 时区处理 若时间戳带时区(timestamptz),AGE 会自动将其转换为 UTC 时间进行计算,避免时区偏移导致的误差。
      1. 性能优化 对大表使用 AGE 时,若涉及索引列(如 hire_date),确保该列有索引以加速查询:
      sql 复制代码
      CREATE INDEX idx_hire_date ON employees(hire_date);

1.4.3.3 更新数据(UPDATE)

sql 复制代码
-- 单表更新(设置工资增长5%)
UPDATE employees 
SET salary = salary * 1.05 
WHERE department_id = 101;

-- 关联更新(基于部门表)
UPDATE employees e
SET email 
= CONCAT(e.emp_name, '@', d.dept_domain)
FROM departments d
WHERE e.department_id = d.dept_id;

1.4.3.4 删除数据(DELETE)

sql 复制代码
-- 单表删除(离职员工)
-- 单表删除(离职员工)
DELETE FROM employees 
WHERE hire_date < '2020-01-01' 
  AND NOT EXISTS (SELECT 1 FROM payroll WHERE emp_id = employees.emp_id);

-- 跨表级联删除(需外键设置级联)
DELETE FROM departments 
WHERE dept_id = 100; -- 自动删除关联的employees记录

1.4.4 事务管理与锁定机制

1.4.4.1 事务控制语句

sql 复制代码
-- 显式事务示例(账户转账)
BEGIN TRANSACTION;          -- 开始事务
UPDATE accounts SET balance = balance - 1000 WHERE user_id = 1;
UPDATE accounts SET balance = balance + 1000 WHERE user_id = 2;
COMMIT;                     -- 提交事务(永久生效)

-- 带保存点的事务
BEGIN;
SAVEPOINT sp1;              -- 设置保存点
UPDATE orders SET status = 'processing' WHERE order_id = 101;
ROLLBACK TO sp1;            -- 回滚到保存点
COMMIT;
ACID特性保障
  • 原子性:事务内操作要么全成功,要么全回滚
  • 一致性:事务前后数据满足约束条件
  • 隔离性 :通过SET TRANSACTION ISOLATION LEVEL控制(默认READ COMMITTED)
  • 持久性:提交后数据永久写入磁盘

1.4.4.2 锁机制

锁类型 模式 作用 示例场景
共享锁(S) SELECT ... FOR SHARE 阻止写操作,允许读并发 报表查询时防止数据修改
排他锁(X) SELECT ... FOR UPDATE 阻止所有并发操作 库存扣减时防止超卖
表级锁 LOCK TABLE ... 锁定整张表(性能影响大) 批量数据初始化

1.4.5 实战案例:电商订单表设计

1.4.5.1 表结构定义

sql 复制代码
CREATE TABLE orders (
    order_id BIGINT PRIMARY KEY DEFAULT generate_ulid(), -- 使用ULID作为主键(比UUID性能高50%)
    user_id INTEGER NOT NULL REFERENCES users(user_id),
    order_time TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    total_amount NUMERIC(12,2) CHECK (total_amount > 0),
    status VARCHAR(20) CHECK (status IN ('待支付', '已支付', '已取消', '已完成')),
    delivery_address JSONB, -- 存储结构化地址数据
    INDEX idx_user_id_status (user_id, status), -- 组合索引优化查询
    TABLESPACE order_ts -- 使用独立表空间
);

1.4.5.2 高频操作示例

订单查询(带索引优化)
sql 复制代码
-- 优化前:全表扫描(耗时120ms)
SELECT * FROM orders WHERE user_id = 1234 AND status = '已完成';

-- 优化后:使用组合索引(耗时8ms)
CREATE INDEX idx_user_id_status ON orders(user_id, status);
批量订单导入(COPY命令)
sql 复制代码
-- 比INSERT速度快10倍以上
COPY orders (user_id, order_time, total_amount, status, delivery_address)
FROM '/data/orders_202401.csv' 
WITH (FORMAT CSV, HEADER, DELIMITER ',', QUOTE '"');

1.4.6 最佳实践与规范

1.4.6.1 命名规范 !!!

对象类型 命名规则 示例
数据库 业务模块_环境(小写) analytics_dev
复数名词(小写下划线分隔) employee_records
字段 小写下划线命名 hire_date
约束 表名_约束类型_字段名 employees_pk_emp_id

1.4.6.2 性能优化建议

    1. **避免使用SELECT ***:显式列出所需字段,减少数据传输
    1. 合理使用JOIN:优先在WHERE子句添加过滤条件,减少关联数据量
    1. 批量操作 :使用INSERT ... VALUES (...),(...)替代单条插入
    1. 事务控制:将高频小事务合并,减少日志写入次数

1.4.6.3 数据完整性保障

  • 外键约束必须定义ON DELETE CASCADESET NULL行为
  • 核心业务表启用TRIGGER进行数据校验
  • 定期运行ANALYZE更新统计信息(建议每日凌晨执行)

1.4.7 常见错误与解决方案

1.4.7.1 约束冲突处理

错误信息 原因分析 解决方案
唯一约束冲突 插入重复数据 使用INSERT ... ON CONFLICT UPDATE
外键约束失败 父表无对应记录 先插入父表数据,或设置DEFERRABLE约束
检查约束违反 数据不符合自定义规则 添加数据清洗步骤,或修改CHECK条件

1.4.7.2 大表操作技巧

sql 复制代码
-- 在线重命名大表(PostgreSQL 11+)
ALTER TABLE large_table RENAME TO new_large_table;

-- 分批次删除数据(避免锁表)
-- 开始一个无限循环,用于分批次删除数据,避免一次性删除大量数据导致锁表和性能问题
WHILE TRUE LOOP
    -- 从 old_data 表中删除创建时间早于 '2023-01-01' 的数据,每次最多删除 10000 条记录
    DELETE FROM old_data WHERE create_time < '2023-01-01' LIMIT 10000;
    -- 检查上一条 DELETE 语句是否删除了任何记录
    -- 如果没有删除任何记录(即 NOT FOUND 条件为真),则说明已经没有符合条件的数据需要删除
    IF NOT FOUND THEN
        -- 当没有符合条件的数据可删除时,退出当前的循环
        EXIT;
    END IF;
    -- 提交当前事务,将已删除的数据永久保存到数据库中
    -- 分批次提交事务可以减少锁的持有时间,提高并发性能
    COMMIT;
-- 结束循环
END LOOP;

1.4.8 总结:构建健壮的数据模型

  • 通过掌握DDL与DML的核心语法,我们能够:
    *
    1. 设计符合业务需求的数据表结构(合理使用约束与索引)
      1. 高效操作数据(批量处理、事务控制、性能优化)
      1. 保障数据完整性与一致性(ACID特性、外键约束)

该文章讲解了PostgreSQL的DDL/DML操作。

后续章节将深入讲解数据清洗技巧(使用CTE、窗口函数)、复杂查询优化(执行计划分析)以及与数据分析工具的集成方法。

建议在实践中遵循"先设计ER图,再编写建表语句"的流程,逐步积累数据库设计经验。

  • CTE 即公共表表达式(Common Table Expressions),它是在 SQL 中定义的临时命名结果集,这些结果集只在当前查询的执行期间存在。
    • CTE 的基本语法如下:

      sql 复制代码
      WITH cte_name (column1, column2, ...) AS (
          -- CTE 的查询语句
          SELECT column1, column2, ...
          FROM table_name
          WHERE condition
      )
      -- 主查询,使用 CTE
      SELECT *
      FROM cte_name;
    • 其中,WITH 关键字用于引入 CTE,cte_name 是 CTE 的名称,括号内可指定列名,AS 后面的括号中是 CTE 的查询语句,最后是使用该 CTE 的主查询。

    • 使用注意事项

      • CTE 的作用域: CTE 只在当前查询中有效,查询执行完毕后,CTE 占用的资源会被释放
      • 性能问题:虽然 CTE 在某些情况下可以提高性能,但在处理大量数据或复杂递归时,可能会导致性能下降。需要根据具体情况进行性能测试和优化。
      • 递归终止条件:在使用递归 CTE 时,必须确保递归有终止条件,否则会导致无限递归,使数据库陷入死循环。
相关推荐
GUIQU.8 分钟前
Function Calling万字实战指南:打造高智能数据分析Agent平台
数据挖掘·数据分析·agent·functioncalling·项目实践
Code哈哈笑15 分钟前
【图书管理系统】用户注册系统实现详解
数据库·spring boot·后端·mybatis
2401_8370885016 分钟前
SQL性能分析
数据库·sql
瓜皮弟子头很铁17 分钟前
多项目共用SQL 添加需要字段
数据库·sql
CryptoRzz39 分钟前
股票数据源对接技术指南:印度尼西亚、印度、韩国
数据库·python·金融·数据分析·区块链
Pluto_CSND1 小时前
hbase shell的常用命令
大数据·数据库·hbase
哈哈真棒1 小时前
sparkSQL读入csv文件写入mysql(2)
数据库·mysql
Cynicism_Smile1 小时前
Mysql 8.0.32 union all 创建视图后中文模糊查询失效
数据库·mysql
小oo呆1 小时前
【自然语言处理与大模型】向量数据库技术
数据库·人工智能·自然语言处理
Aurora_NeAr2 小时前
Redis设计与实现——Redis命令参考与高级特性
数据库·redis·缓存