PostgreSQL 入门学习教程,从入门到精通,PostgreSQL 16 语法知识点与案例详解(1)

PostgreSQL 入门学习教程,从入门到精通,PostgreSQL 16 语法知识点与案例详解(1)

PostgreSQL 16 语法知识点与案例详解


一、数据库基础

1. 什么是数据库?

数据库(Database)是结构化数据的集合,用于高效存储、检索和管理数据。PostgreSQL 是一个功能强大的开源关系型数据库管理系统(RDBMS)。


2. 表(Table)

表是数据库中存储数据的基本结构,由行(记录)和列(字段)组成。

✅ 语法:创建表
CREATETABLE table_name ( column1 datatype constraints, column2 datatype constraints,...);
📌 案例:创建学生表
-- 创建一个名为 students 的表CREATETABLE students ( id SERIALPRIMARYKEY,-- SERIAL 自动递增,PRIMARY KEY 主键约束 name VARCHAR(50)NOTNULL,-- 姓名,最大50字符,不允许为空 age INTCHECK(age >=0),-- 年龄,整数,必须大于等于0 email VARCHAR(100)UNIQUE,-- 邮箱,唯一值 created_at TIMESTAMPDEFAULTCURRENT_TIMESTAMP-- 创建时间,默认当前时间);-- 注释:-- SERIAL 是 PostgreSQL 特有的自增整数类型-- PRIMARY KEY 唯一标识每一行-- NOT NULL 不允许为空-- CHECK 约束数据范围-- UNIQUE 不允许重复-- DEFAULT 设置默认值

3. 数据类型

PostgreSQL 支持丰富的数据类型:

类型说明示例
SERIAL自增整数id SERIAL
VARCHAR(n)可变长度字符串name VARCHAR(50)
INT整数age INT
TEXT长文本description TEXT
BOOLEAN布尔值is_active BOOLEAN
DATE日期birth_date DATE
TIMESTAMP日期+时间created_at TIMESTAMP
NUMERIC(p,s)精确小数price NUMERIC(10,2)
📌 案例:创建商品表(包含多种数据类型)
CREATETABLE products ( product_id SERIALPRIMARYKEY, product_name VARCHAR(100)NOTNULL, price NUMERIC(10,2)CHECK(price >0),-- 价格,保留2位小数,必须大于0 is_available BOOLEANDEFAULTTRUE,-- 是否上架,默认为真 description TEXT,-- 商品描述,长文本 release_date DATE,-- 发布日期 last_updated TIMESTAMPDEFAULTNOW()-- 最后更新时间);

4. 主键(Primary Key)

主键用于唯一标识表中的每一行,不能为 NULL,且必须唯一。

✅ 语法:定义主键
-- 在列定义时指定 column_name datatype PRIMARYKEY-- 或在表级指定(支持复合主键)PRIMARYKEY(col1, col2)
📌 案例:订单明细表(复合主键)
CREATETABLE order_items ( order_id INTNOTNULL, product_id INTNOTNULL, quantity INTCHECK(quantity >0),PRIMARYKEY(order_id, product_id)-- 复合主键:一个订单中同一商品只能出现一次);

二、SQL语言基础

1. 插入数据(INSERT)

INSERTINTO table_name (col1, col2,...)VALUES(val1, val2,...);
📌 案例:
-- 插入学生数据INSERTINTO students (name, age, email)VALUES('张三',20,'[email protected]');-- 插入多条数据INSERTINTO students (name, age, email)VALUES('李四',22,'[email protected]'),('王五',19,'[email protected]');

2. 查询数据(SELECT)

SELECT column1, column2 FROM table_name WHERE condition;
📌 案例:
-- 查询所有学生SELECT*FROM students;-- 查询特定列SELECT name, age FROM students;-- 带条件查询SELECT name, email FROM students WHERE age >=20;-- 排序SELECT*FROM students ORDERBY age DESC;-- 限制结果数量SELECT*FROM students LIMIT3;

3. 更新数据(UPDATE)

UPDATE table_name SET column1 = value1 WHERE condition;
📌 案例:
-- 更新张三的邮箱UPDATE students SET email ='[email protected]'WHERE name ='张三';-- 更新多个字段UPDATE students SET age = age +1,-- 年龄+1 last_updated =NOW()-- 更新时间WHERE id =1;

4. 删除数据(DELETE)

DELETEFROM table_name WHERE condition;
📌 案例:
-- 删除年龄小于18的学生DELETEFROM students WHERE age <18;-- ⚠️ 删除所有数据(慎用!)DELETEFROM students;-- 更安全的方式是使用 TRUNCATE(重置自增ID)TRUNCATETABLE students RESTART IDENTITY;

三、PostgreSQL 特性与优势

1. 客户机-服务器架构

PostgreSQL 采用 C/S 架构,客户端通过网络连接服务器进行数据操作。

# 命令行连接示例(需安装 psql) psql -h localhost -U postgres -d mydb 

2. 开源优势

  • 免费使用,无商业限制
  • 社区活跃,持续更新
  • 支持扩展(如 PostGIS、JSONB、全文搜索等)

3. PostgreSQL 特色语法

✅ 返回插入/更新的值(RETURNING)
-- 插入后返回自动生成的IDINSERTINTO students (name, age, email)VALUES('赵六',25,'[email protected]')RETURNING id, name;-- 更新后返回旧值或新值UPDATE students SET age =30WHERE name ='赵六'RETURNING*;-- 返回更新后的整行
✅ 使用 WITH(CTE,公共表表达式)
-- 查询年龄大于平均年龄的学生WITH avg_age AS(SELECTAVG(age)as avg_val FROM students )SELECT name, age FROM students, avg_age WHERE students.age > avg_age.avg_val;
✅ JSONB 数据类型(PostgreSQL 特色)
CREATETABLE user_profiles ( id SERIALPRIMARYKEY, user_id INTUNIQUE, profile JSONB -- 存储灵活的JSON结构);-- 插入JSON数据INSERTINTO user_profiles (user_id, profile)VALUES(1,'{"name": "Alice", "hobbies": ["reading", "swimming"], "active": true}');-- 查询JSON字段SELECT profile->>'name'AS username FROM user_profiles WHERE profile->>'name'='Alice';-- 查询数组元素SELECT*FROM user_profiles WHERE profile->'hobbies' ? 'reading';-- 是否包含 "reading"

四、数据库访问技术

1. 使用 psql 命令行工具

# 登录 psql -U postgres -d mydb # 常用命令\l -- 列出所有数据库 \c mydb -- 切换数据库 \dt -- 列出当前数据库所有表 \d students -- 查看表结构 \q -- 退出 

2. 使用图形化工具(如 pgAdmin、DBeaver)

略 —— 可视化操作,适合初学者。

3. 编程语言连接(Python + psycopg2 示例)

import psycopg2 # 连接数据库 conn = psycopg2.connect( host="localhost", database="mydb", user="postgres", password="yourpassword") cur = conn.cursor()# 执行查询 cur.execute("SELECT name, age FROM students WHERE age > %s",(20,)) rows = cur.fetchall()for row in rows:print(f"姓名: {row[0]}, 年龄: {row[1]}") cur.close() conn.close()

五、综合性实战案例

🎯 案例:图书管理系统

步骤1:创建数据库和表
-- 创建数据库(在 psql 中执行)CREATEDATABASE library;-- 切换数据库 \c library -- 创建作者表CREATETABLE authors ( author_id SERIALPRIMARYKEY, name VARCHAR(100)NOTNULL, birth_year INT, country VARCHAR(50));-- 创建图书表CREATETABLE books ( book_id SERIALPRIMARYKEY, title VARCHAR(200)NOTNULL, author_id INTREFERENCES authors(author_id)ONDELETECASCADE,-- 外键 publish_year INT, isbn VARCHAR(13)UNIQUE, price NUMERIC(8,2), in_stock BOOLEANDEFAULTTRUE);-- 创建借阅记录表CREATETABLE borrows ( borrow_id SERIALPRIMARYKEY, book_id INTREFERENCES books(book_id), borrower_name VARCHAR(100), borrow_date DATEDEFAULTCURRENT_DATE, return_date DATE, is_returned BOOLEANDEFAULTFALSE);
步骤2:插入测试数据
-- 插入作者INSERTINTO authors (name, birth_year, country)VALUES('鲁迅',1881,'中国'),('村上春树',1949,'日本'),('J.K.罗琳',1965,'英国')RETURNING author_id;-- 插入图书(假设作者ID为1,2,3)INSERTINTO books (title, author_id, publish_year, isbn, price)VALUES('呐喊',1,1923,'9787020000011',35.00),('挪威的森林',2,1987,'9784000000022',45.50),('哈利波特与魔法石',3,1997,'9780747532699',55.00);-- 插入借阅记录INSERTINTO borrows (book_id, borrower_name, return_date)VALUES(1,'张三','2025-09-20'),(2,'李四',NULL);-- 未归还
步骤3:综合查询
-- 查询所有在借书籍(未归还)SELECT b.title AS 书名, a.name AS 作者, br.borrower_name AS 借阅人, br.borrow_date AS 借出日期 FROM borrows br JOIN books b ON br.book_id = b.book_id JOIN authors a ON b.author_id = a.author_id WHERE br.is_returned =FALSEOR br.return_date ISNULL;-- 查询每本书的借阅次数SELECT b.title,COUNT(br.borrow_id)AS 借阅次数 FROM books b LEFTJOIN borrows br ON b.book_id = br.book_id GROUPBY b.book_id, b.title ORDERBY 借阅次数 DESC;-- 查询最贵的3本书SELECT title, author_id, price FROM books ORDERBY price DESCLIMIT3;
步骤4:更新与维护
-- 标记某本书已归还UPDATE borrows SET is_returned =TRUE, return_date =CURRENT_DATEWHERE borrow_id =1;-- 删除不再出版的书籍(级联删除借阅记录)DELETEFROM books WHERE book_id =3;-- 由于外键 ON DELETE CASCADE,相关借阅记录也会被自动删除

✅ 学习建议

  1. 动手实践:每个语法点都要亲自敲代码,观察结果。
  2. 善用 \d\dt:在 psql 中查看表结构。
  3. 阅读官方文档:https://www.postgresql.org/docs/16/
  4. 尝试复杂查询:多表 JOIN、子查询、窗口函数等。
  5. 学习事务与索引:后续章节重点。

📚 附:常用命令速查表

功能SQL 语句
创建表CREATE TABLE ...
插入数据INSERT INTO ... VALUES ...
查询数据SELECT ... FROM ... WHERE ...
更新数据UPDATE ... SET ... WHERE ...
删除数据DELETE FROM ... WHERE ...
添加列ALTER TABLE ... ADD COLUMN ...
删除表DROP TABLE ...
查看表结构\d table_name(psql中)
返回插入IDINSERT ... RETURNING id
事务BEGIN; ... COMMIT; / ROLLBACK;

📌 提示:PostgreSQL 16 新增了并行化改进、逻辑复制增强、SQL/JSON 标准支持等,建议后续学习时关注官方 Release Notes。


✅ 本章内容覆盖了从零开始学习 PostgreSQL 所需的核心语法和实战技能,建议保存为学习手册,反复练习!

Read more

五大经典排序算法:插入、希尔、冒泡、选择、堆排序全攻略

五大经典排序算法:插入、希尔、冒泡、选择、堆排序全攻略

目录 --------------插入排序------------- 1、插入排序思想 2、示例代码 3、效率分析 --------------希尔排序------------- 1、希尔排序思想 2、示例代码 3、效率分析 --------------选择排序------------- 1、选择排序思想 2、示例代码 3、效率分析 ---------------堆排序-------------- 1、堆排序思想 2、示例代码 3、效率分析 --------------冒泡排序------------- 1、冒泡排序思想 2、示例代码 3、效率分析 上述五大排序性能对比: --------------插入排序------------- 1、插入排序思想 插入排序的核心思想是逐步构建有序序列: 将数组分为 “已排序” 和 “未排序” 两部分,初始时已排序部分只包含第一个元素。 每次从未排序部分取出第一个元素,将其向前插入到已排序序列中的正确位置,使得插入后的序列依然保持有序。

By Ne0inhk
Flutter 组件 humanize 的适配 鸿蒙Harmony 深度进阶 - 驾驭多语言复数逻辑算法、实现鸿蒙端中式大额单位感知与极致人性化文本渲染方案

Flutter 组件 humanize 的适配 鸿蒙Harmony 深度进阶 - 驾驭多语言复数逻辑算法、实现鸿蒙端中式大额单位感知与极致人性化文本渲染方案

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 humanize 的适配 鸿蒙Harmony 深度进阶 - 驾驭多语言复数逻辑算法、实现鸿蒙端中式大额单位感知与极致人性化文本渲染方案 前言 在前文我们掌握了 humanize 进行基础数据转换的方法。但在鸿蒙(OpenHarmony)面向全球市场的布局中,真正的技术挑战往往隐藏在极其琐碎的“语言表达”中。例如:在英文中我们说 1 items 是错误的,必须是 1 item 与 2 items;而在中文环境下,我们虽然没有复数形变,但却有“万、亿”这类独特的四位一级计数逻辑。 一个真正具备“高级感”的鸿蒙应用,不应在数据展示上显得僵硬且带有明显的机器翻译痕迹。 本文将作为 humanize 适配的进阶篇,带你攻克多语言复数(Pluralization)

By Ne0inhk
【数据结构与算法】链表超全分类!从结构入门到双向链表初始化实现

【数据结构与算法】链表超全分类!从结构入门到双向链表初始化实现

🔥小龙报:个人主页 🎬作者简介:C++研发,嵌入式,机器人等方向学习者 ❄️个人专栏:《C语言》《【初阶】数据结构与算法》 ✨ 永远相信美好的事情即将发生 文章目录 * 前言 * 一、链表的分类与说明 * 1.1 单向或者双向 * 1.2 带头或者不带头 * 1.3 循环或者不循环 * 二、双向链表 * 2.1 双向链表的定义 * 2.2 双向链表中哨兵位头节点的初始化 * 三、代码展现 * 3.1 List.h * 3.2 List.c * 3.3 test.c * 总结与每日励志 前言 链表是数据结构入门阶段的核心知识点,

By Ne0inhk

优选算法——链表

💁‍♂️个人主页:进击的荆棘 👇作者其它专栏: 《数据结构与算法》《算法》《C++起始之路》 相关题解 1.两数相加 算法思路(模拟): 两个链表都是逆序存储数字的,即两个链表的个位数、十位数等都已经对应,可以直接相加。在相加过程中,我们要注意是否产生进位,产生进位时需要将进位和链表数字一同相加。若产生进位的位置在链表底部,即答案位数比原链表位数长一位,还需要再new一个结点存储最高位。 /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(

By Ne0inhk