学习的是https://www.bilibili.com/video/BV1HyWxzQE7K?spm_id_from=333.788.player.switch&vd_source=0ea1552687da3b191a212f42633ae406提供的教学视频,PSQL的12版本。基本内容应该不会差太多,如果有区别,我会直接记下最新操作的笔记。

1. Postgresql和MySQL的对比

image-20251127111754926

2. postgresql安装

安装过程省略,推荐在linux上进行安装使用,并且Linux最好是最小安装,不要带GUI界面的那种。在安装完成之后,由于postgresql不推荐使用root管理,它会默认给你创建一个用户:postgres。所以在玩PGSQL之前,要先切换到postgres用户。

3. postgresql配置

postgresql的主要配置放在数据目录(data/)下,postgresql.conf和pg_hba.conf。

/etc/postgresql/14/main/pg_hba.conf

/etc/postgresql/14/main/postgresql.conf

3.1 远程连接配置

主用户:

然后在文件底部加入,这表示允许任意地址的所有用户连接所有数据库。修改后保存文件。

然后编辑:

将里面的listen_addresses改为*

保存文件后重启postgresql:

3.2 日志配置

为什么要配置日志?

✅ 1. SQL 报错很难查

例如你的应用报:

但你不知道是哪一条 SQL 出错。 开启 SQL 日志后,你能看到完整 SQL。

✅ 2. 性能调优离不开日志

你可以找出:

所有这些都必须从日志判断。

✅ 3. 安全审计

可以记录:

这是企业应用、线上系统必备的。

⚠️ 结论:不配置日志 = 出问题没地方查

按照下面来配置即可:

image-20251127134220132

postgresql默认情况下,只保存7天的日志,循环覆盖。下面是参数说明:

image-20251127134330956

4. 基操用户操作

进入到psql命令行之后。

\help,查看数据库级别的命令:

image-20251127135130000

\help 具体的命令,查看具体命令的使用方法,比如说\help create user

image-20251127135310235

\?,查看服务级别的命令,按q退出这个界面:

image-20251127135911618

\q,退出psql命令行:

image-20251127140033673

\du,查看全部用户:

image-20251127141411475

下面是一些实际操作:

创建一个超级管理员用户。

image-20251127141449874

为什么这里的回显是create role呢?我明明是创建了用户啊,原因是从 PostgreSQL 8.1 开始,CREATE USER 只是 CREATE ROLE 的语法糖(别名)。

换句话说:

只是默认带上 LOGIN(可以登录数据库) 属性而已。

注意,数据库的用户和我认为的前端网站的登录用户,对于数据库的操作是完全不同的概念。

数据库用户是数据库内部的账号,用来:

📌 DB 用户是给后端/服务用的,不是给网站会员用的。下节课说的用户权限,指的是DB用户的权限,指的是可以直接连接这个数据库后的操作权限。

 

网站用户是你的网站/应用里的普通用户:

项目数据库用户(DB User)网站用户(App User)
定义PostgreSQL 内部的账号存在 users 表里的业务账号
用于系统访问数据库用户访问网站
数量很少很多
控制权限SQL 权限应用代码
不能互相替代

 

 

 

 

5. 基操权限操作和小任务

PGSQL的逻辑结构

image-20251127141753738

image-20251127142107462

这部分的内容还是蛮重要的,因为数据安全的重要性不言而喻。但是这部分先不用管,因为命令很简单,到时候搜索即可。

postgresql的逻辑结构:

我们用最直观的方式,把 PostgreSQL 的逻辑结构从“大到小”一层一层讲清楚,你看完就彻底明白了。PostgreSQL 逻辑结构全景图(从大到小)

层级名称说明举个生活中的比喻
1. 整个 PostgreSQL 服务集群(Cluster)你启动一个 PostgreSQL 服务(一个端口 5432),它就是一个集群一整个学校
2. 集群下面有很多数据库(Database)集群里可以创建很多个数据库,彼此数据完全隔离学校里有许多独立的教学楼(文科楼、理科楼)
3. 每个数据库里面有Schema(模式)一个数据库里又可以再划分很多 schema,相当于子命名空间每栋教学楼里有很多教室(schema)
4. Schema 里面放对象(表、视图、函数、序列等)真正的表、视图、函数都放在某个 schema 里教室里放课表、黑板、学生(表、数据)

下面用一张图帮你记住(文字版):

每个层级最核心的要点

层级关键点(你一定要记住)
Cluster一个 PostgreSQL 服务进程(一个端口)就是一个集群,全局共享一套用户(角色)和 tablespace
Database数据完全隔离!不同数据库之间的表、函数同名也不冲突;连接时必须指定连哪个数据库(psql -d company_db)
Schema只是命名空间,不隔离数据!同一个数据库里不同 schema 的表可以互相 join;全路径是 database.schema.table
Table 等对象真正存放数据的地方,必须属于某个 schema

实际工作中最常用的路径写法当你写 SQL 时,完整对象名是这样写的:

再举一个真实项目的典型结构(强烈推荐你也这么用)

这样做的好处:

总结一句话记住了:PostgreSQL 逻辑结构只有 4 层: 集群 → 多个数据库(完全隔离) → 每个数据库里多个 schema(命名空间) → schema 里放表、视图、函数等。相当于: 一个 PostgreSQL 服务 = 一所大学 多个数据库 = 多栋教学楼(楼和楼之间完全不联通) 多个 schema = 每栋楼里的不同教室分区 表 = 教室里的课桌和学生搞清楚这四层关系后,你再看任何 PostgreSQL 项目结构都不会懵了!

下面是在一个项目中使用postgresql的过程,从中可以看到postgresql的各种概念的使用。

  1. 本地/服务器上创建数据库、用户
  2. 推荐的数据库 & schema 结构
  3. 初始化表(迁移方式)
  4. Next.js 14(App Router)项目里怎么安全、优雅地连接和操作 PostgreSQL
  5. 生产环境部署注意事项(Vercel / 自建服务器)

一、PostgreSQL 端:完整建库建用户脚本(直接拷贝执行)

二、推荐的表结构示例(用迁移工具管理,后面会讲)

三、Next.js 项目端完整配置(Next.js 14 App Router 推荐做法 2025 年版)1. 安装依赖(2025 年最推荐组合)

下面分别给出 Prisma(最推荐) 和 Drizzle(轻量) 两套方案,任选其一。方案 A:Prisma(99% 新项目选这个)

  1. .env 文件(本地和生产都放这里)
  1. prisma/schema.prisma(关键:多 schema 配置)
  1. 迁移命令(每次改 schema 后执行)
  1. 在 Next.js 中使用(lib/prisma.ts)
  1. 在 Server Component / Route Handler / Server Action 里随便用

四、生产部署最重要几件事(不能忘!)

项目推荐做法
数据库托管Neon.tech(免费层超强) / Supabase Postgres / Railway / AWS RDS
环境变量Vercel → Project Settings → Environment Variables 里加 DATABASE_URL
SSL生产必须强制 sslmode=require
连接池Vercel/Serverless 环境必须用 PgBouncer 或 Neon 的 serverless driver
Prisma 加速推荐开启 Prisma Accelerate(连接池 + 边缘缓存)
敏感密码永远不要写死,用 Vercel / Railway 的加密环境变量
备份Neon 自动 PITR,Supabase 也有自动备份

五、完整一步步操作清单(直接照着做就行)

  1. 装好 PostgreSQL(本地开发)或注册 Neon/Supabase(推荐)
  2. 执行上面第一段 SQL 创建用户、数据库、schema
  3. 创建 Next.js 项目 npx create-next-app@latest myapp --ts
  4. 装 Prisma → prisma init → 配置 schema.prisma
  5. 写完模型 → npx prisma migrate dev --name init
  6. 开发中使用,部署时只跑 npx prisma migrate deploy
  7. 把 DATABASE_URL 填到 Vercel 环境变量 → 部署

6. pgAdmin图形化界面连接和基本操作

image-20251127152612147

image-20251127153014985

连接成功之后,可以打开命令行:

image-20251127153257479

image-20251127153311547

打开查询工具:

image-20251127153424076

显示中文界面

image-20251127153903931

7. 数据类型

90%情况下,只需要关注数字、字符串、时间这三种类型即可。

总结:你日常只需要记住这几行就行

2025 年实际项目中 99% 情况你只需要记住下面这 10 个就够了(生产推荐组合)

场景推荐类型为什么
主键uuid 或 bigserialuuid 分布式安全,bigserial 最简单
用户 IDuuid防止泄露用户数量,分布式友好
自增 IDbigserial简单粗暴,顺序递增
金额numeric(12,2) 或 integer(存分)绝对精确,金融级
文本text别再用 varchar 了,性能一样,没长度限制
邮箱citext自动忽略大小写,不用再 upper(email)
时间timestamptz自动带时区,存 UTC,全球通用
软删除时间timestamptzdeleted_at TIMESTAMPTZ NULL
状态/枚举text + check 约束比 enum 类型灵活,改起来不锁表
配置/扩展字段jsonb什么都能存,还能建 GIN 索引
标签、角色列表text[] 或 jsonb数组简单,复杂结构用 jsonb

枚举类型怎么写(推荐替代方案)不要用 PostgreSQL 原生 enum(改起来很麻烦),改用 check 约束:

详细说明:

大类数据类型常见写法 / 示例什么时候用(一句话记住)
数字类型smallintint2极小整数,省空间,范围 -32k ~ +32k
 integerint, int4最常用整数,几乎所有 id、计数都用这个
 bigintint8超大数字,订单号、雪花 ID、金额分等用这个
 smallserialserial22字节自增 id(1~32767)
 serialserial44字节自增,最常用
 bigserialserial88字节自增,永远不会用完
 numeric / decimalnumeric(10,2)金融级精确小数,金额必用(不要用 float)
 real / float4real单精度浮点,科学计算用
 double precision / float8double precision双精度浮点,普通科学计算
货币类型moneymoney已不推荐(有精度问题),改用 numeric(12,2) + 分存储
文本类型texttext2025 年最推荐!啥都存 text,性能和 varchar 几乎一样,无长度限制
 varchar[n]varchar(255)只有在需要限制长度做校验时才用
 char[n]char(10)极少用,定长,基本没人用
 citextcitext不区分大小写的 text,非常好用(需 create extension citext;)
布尔类型booleanbool, true/false只有 true / false / null 三种值
时间类型timestamptimestamp不带时区,存本地时间(大部分项目用这个)
 timestamptztimestamp with time zone带时区,推荐!所有生产项目都用 timestamptz(内部存 UTC)
 datedate只存日期
 timetime只存时间
 timetztime with time zone时间带时区
 intervalinterval时间间隔,比如 “3 days”、 “2 hours”
UUIDuuiduuid分布式唯一 ID 必备(比 bigint 更安全)
JSONjsonjson存结构化但不经常查的日志、配置
 jsonbjsonb2025 年最爱!支持索引、二进制存储、查询超快,所有半结构化数据都用 jsonb
数组类型任意类型[]text[], int[], timestamptz[]一列存多个值,比如标签、角色列表
范围类型int4range, int8range, tsrange, tstzrange, daterange, numrangeint4range('[1,10]', '[]')非常强大,比如价格区间、预约时间段、有效期
网络地址类型inetinet存 IPv4/IPv6 + 子网掩码
 cidrcidr存 IP 网段
 macaddrmacaddrMAC 地址
几何类型point, line, circle, box, polygon, path, lsegpoint(1.5, 2.5)做地图、GIS 用(配合 PostGIS 扩展更强)
货币/金额专用money → 废弃改用 numeric(12,2) 或 integer(存分) 
特殊类型byteabytea存二进制文件、图片小文件(大文件建议放对象存储)
 xmlxml存 XML(几乎没人用)
 bit / bit varyingbit(8), varbit位操作
 tsvector / tsquerytsvector全文搜索专用(配合 GIN 索引超快)
 hstorehstorekey-value 键值对(老项目用,现在基本被 jsonb 取代)
 ltreeltree树形结构、路径(如 1.2.3.4 表示层级)
 int4multirange, etc.多段范围(PG14+)比如一个用户一天有多个可用时间段

8. PGSQL操作

8.1 单引号和双引号

单引号

在PGSQL中,写SQL语句时,单引号 ('...') 用于界定 字符串常量 (String Literals),也就是 SQL 语句中用作数据的文本值。

核心规则:
示例:

双引号

双引号 ("...") 用于界定 标识符 (Identifiers),即数据库对象(表名、列名、模式名、函数名等)的名称。

核心规则:
示例:
A. 默认行为 (不使用双引号)
B. 使用双引号 (强制区分大小写)

最佳实践: 强烈建议不要在标识符中使用双引号,除非你确实需要使用空格或保留字。遵循小写和下划线的命名约定 (e.g., user_account) 可以使你的 SQL 代码更简洁、更具可移植性。

8.2 数据类型转换

方式一:只需要在值的前面,添加上具体的数据类型即可

image-20251127162559706

方式二:在具体值后面,添加上 ::类型 来指定

image-20251127162715697

完整写法:

image-20251127162747940

 

8.3 布尔类型

有三种值:true、false、null。

灵活的输入值 (Valid Literal Values)

这是 PostgreSQL 与其他数据库最大的不同点之一。它非常宽容,除了标准的 TRUE/FALSE,还接受多种字符串表示形式(不区分大小写)。

状态标准 SQL 写法允许的字符串写法 (不区分大小写)允许的数字写法
真 (True)TRUE't', 'true', 'y', 'yes', 'on''1'
假 (False)FALSE'f', 'false', 'n', 'no', 'off''0'

注意: 使用字符串形式(如 'yes')时,必须加单引号;使用关键字 TRUEFALSE 时不需要引号。

如果要使用字符串或者数字写法来当作布尔值,select的时候要进行转换才能称为boolean类型

推荐写法 (简洁)

不需要写 = TRUE= FALSE

处理 NULL 值 (三值逻辑)

这是布尔类型最容易出错的地方。NULL 既不是 TRUE 也不是 FALSE

如果你想查询“所有未明确被禁止”的用户(即包含 TRUENULL,但不包含 FALSE),你需要使用 IS NOT 语法:

boolean类型在做and or的逻辑操作时,结果有哪些

1. 逻辑与 (AND) 的结果

AND 操作只有在所有输入都为 TRUE 时,结果才为 TRUE。只要有任何一个操作数为 FALSE,结果立即为 FALSE

ABA AND B解释
TRUETRUETRUE两个条件都满足
TRUEFALSEFALSE有一个条件不满足
FALSEFALSEFALSE两个条件都不满足
TRUENULLNULL结果取决于 NULL 是否为 TRUE,但我们不知道,所以是未知。
FALSENULLFALSE无论 NULL 是 TRUE 还是 FALSE,由于其中一个操作数已经是 FALSE,根据短路原则,结果一定是 FALSE。
NULLNULLNULL两个都是未知
2. 逻辑或 (OR) 的结果

OR 操作只要有一个输入为 TRUE,结果就为 TRUE。只有当所有输入都为 FALSE 时,结果才为 FALSE

ABA OR B解释
TRUETRUETRUE有一个条件满足
TRUEFALSETRUE有一个条件满足
FALSEFALSEFALSE两个条件都不满足
TRUENULLTRUE无论 NULL 是 TRUE 还是 FALSE,由于其中一个操作数已经是 TRUE,根据短路原则,结果一定是 TRUE。
FALSENULLNULL结果取决于 NULL 是否为 TRUE,但我们不知道,所以是未知。
NULLNULLNULL两个都是未知
3. 逻辑非 (NOT) 的结果

NOT 操作就是对操作数取反。

ANOT A
TRUEFALSE
FALSETRUE
NULLNULL

4. 总结与在 WHERE 子句中的应用

理解三值逻辑最重要的一点,在于它如何影响数据库查询中的 WHERE 子句:

WHERE 子句只会返回那些其条件表达式计算结果为 TRUE 的行。

这意味着:

  1. 如果条件计算结果是 TRUE,则该行被返回
  2. 如果条件计算结果是 FALSE,则该行被过滤
  3. 如果条件计算结果是 NULL (未知),则该行也被过滤

最佳实践建议

  1. 命名规范: 给布尔字段命名前加上 is_has_can_ 等前缀,这样代码的可读性极高。

    • is_visible, has_permission, can_login
    • visible, permission, login (容易被误认为是名词或字符串)
  2. 默认值: 尽量在建表时给布尔字段设置 DEFAULT 值(通常是 FALSE)。这可以避免在业务逻辑中处理棘手的 NULL 值。

  3. 避免使用 CHAR(1) 或 INT: 虽然可以用 0/1'Y'/'N' 来模拟,但使用原生的 BOOLEAN 类型存储效率更高,且语义更明确,能防止无效数据的插入(例如防止插入 'X')。

8.4 数值类型

8.4.1 整型

类型名称存储空间最小/最大值范围 (近似值)适用场景
SMALLINT2 字节计数较小的标志或状态码、内存占用敏感的巨大表。
INTEGER4 字节 亿最常用和推荐的默认选择。适用于大多数 ID、计数和常规数值。
BIGINT8 字节巨大的 ID(比如说雪花ID)、高流量表的主键、货币价值、天文数字、系统计数。

类型别名:

类型名称 (最常用)存储空间别名 1 (SQL 标准)别名 2 (PostgreSQL 内部/SQL 简写)
SMALLINT2 字节INT2
INTEGER4 字节INT4INT
BIGINT8 字节INT8

8.4.2 浮点型

就关注两种类型(本质上就只有一个)

针对浮点类型的数据,就使用 numeric ,不用考虑其它。

语法:NUMERIC(p, s)

NUMERIC 允许您指定精度和标度:

  1. (Precision,精度): 数字的总位数(小数点左右)。
  2. (Scale,标度): 小数点右侧的位数。

示例:

8.4.3 序列

序列是 PostgreSQL 用于生成唯一、有序、自动递增(或递减)的整数的数据库对象。它们是实现自动增长主键的基石。MySQL中的主键自增,是基于auto_increment来实现的,MySQL里面没有序列对象。PGSQL和Oracle十分相似,支持序列:sequence。PGSQL是没有auto_increment的。

序列的定义和核心用途
A. 定义 (What is a Sequence?)

序列是一个独立的数据库对象,它不属于任何表,但可以被任何表或查询引用。它的主要作用是维护一个计数器,并保证在任何时间点,只要调用它,就能返回一个唯一原子性递增的数值。

B. 核心用途

序列最主要的应用就是作为表的主键 (Primary Key) 生成器,确保每条新插入的记录都有一个独一无二的 ID

序列的正常构建方式
A. 创建序列

默认情况下,sequence的起始值是0,最大值9223372036854775807,每次nextval递增1。

创建之后可以看到:

image-20251204220541011

B. 主要的操作函数
函数作用示例
nextval('seq_name')获取并前进:原子性地递增序列,并返回序列的下一个值。SELECT nextval('sku_sequence');
currval('seq_name')获取当前值:返回当前会话中最近一次由 nextval() 取出的值。SELECT currval('sku_sequence');
setval('seq_name', value)设置值:用于手动设置序列的当前值(通常用于迁移数据或重置)。SELECT setval('sku_sequence', 5000);
C. 应用-当作表的主键生成器

然后执行多次插入语句,就可以看到id是自增的。

image-20251204221128235

序列的简单构建方式

序列的正常构建方式,需要先专门构建一个序列表。PGSQL提供了序列这种语法糖,可以在声明表结构的时候,直接指定序列的类型即可。

SERIAL 的本质:自动化脚本

SERIAL 本身并不是一种数据类型。它是一个方便的快捷方式(或称“语法糖”),它指示 PostgreSQL 在您创建表时,自动执行三个独立的 SQL 步骤,从而将一列变成自动递增的唯一标识符。

当您执行 CREATE TABLE t (id SERIAL); 时,数据库内部实际执行了以下操作:

步骤实际操作对应的 SQL 语句 (以 SERIAL 为例)
1. 创建序列自动创建一个新的 序列对象,命名通常是 表名_列名_seqCREATE SEQUENCE table_id_seq START WITH 1 INCREMENT BY 1;
2. 设置默认值将该列的默认值设置为调用新创建的序列的 nextval() 函数。ALTER TABLE table ALTER COLUMN id SET DEFAULT nextval('table_id_seq');
3. 设置类型和约束将该列的数据类型设置为基础的整型,并加上 NOT NULL 约束。ALTER TABLE table ALTER COLUMN id TYPE INTEGER NOT NULL;

核心优势: 您只需要写一行 id SERIAL,PostgreSQL 就为您完成了复杂的序列创建、关联和约束设置工作。

三种 SERIAL 变体
SERIAL 类型对应基础整型存储空间范围
SMALLSERIALSMALLINT (INT2)2 字节
SERIALINTEGER (INT4)4 字节 亿
BIGSERIALBIGINT (INT8)8 字节

最佳实践选择:

SERIAL 的重要特性:所有权与依赖性

使用 SERIAL 创建的序列对象与手动创建的序列对象有一个关键区别:所有权 (Ownership)

A. 自动所有权

当您使用 SERIAL 创建一列时,PostgreSQL 会自动将序列的所有权归属于该表列。

在这种情况下,序列 users_user_id_seq 归属于 users 表的 user_id 列。

image-20251204224004643

B. 级联删除 (Dependency)

由于所有权关系的存在,序列具有强大的依赖性:

当您删除(DROP)包含 SERIAL 列的表时,PostgreSQL 会自动删除关联的序列对象。我试过了,是真的。

这使得管理非常方便,不会在数据库中留下无用的序列垃圾。如果序列是手动创建的,您必须手动删除序列(DROP SEQUENCE)。

C. 序列名称查找

如果您需要检查或修改序列的属性(如手动重置起始值),您需要知道它的名字。PostgreSQL 默认的命名规则是:[表名]_[列名]_seq

示例:重置序列值

假设您的 users 表因为数据导入导致序列号混乱,需要从 10000 开始:

简单构建方式和正常构建方式的区别
操作SERIAL 语法显式序列 (手动)
创建表CREATE TABLE t (id SERIAL);CREATE TABLE t (id INTEGER NOT NULL DEFAULT nextval('t_id_seq'));
序列对象自动创建,例如 t_id_seq必须手动创建:CREATE SEQUENCE t_id_seq;
依赖性序列依赖于列,删除列会删除序列。序列独立存在,需要手动删除 (DROP SEQUENCE)。

8.4.4 数值类型的常见操作

1. 基础数学运算符 (Arithmetic Operators)

这是最常用的一组操作,遵循标准的数学规则。

运算符名称示例 (A = 10, B = 3)结果 (INTEGER)
+加法A + B13
-减法A - B7
*乘法A * B30
/除法A / B3 (整型除法,舍弃小数)
%求余 (模运算)A % B1
^幂运算A ^ 2100

⚠️ 注意整型除法:

当使用两个整型(INTEGER 或 BIGINT)进行 / 除法时,结果仍然是整型,任何小数部分都会被截断 (truncated),而不是四舍五入。

如果需要精确的浮点数结果,请确保至少有一个操作数是浮点类型:

SELECT 10.0 / 3;

2. 比较和逻辑操作 (Comparison and Logic)

这些操作返回一个布尔值 (TRUE, FALSE, 或 NULL),主要用于 WHEREHAVING 子句进行过滤。

运算符名称示例
=等于WHERE price = 19.99
<小于WHERE age < 18
>大于WHERE score > 90
<=小于等于WHERE count <= 100
>=大于等于WHERE quantity >= 10
!=<>不等于WHERE status != 0
BETWEEN在...之间 (含边界)WHERE value BETWEEN 10 AND 20
IN在列表中WHERE id IN (1, 5, 8)
3. 聚合函数 (Aggregate Functions)

聚合函数用于对一组行(通常是分组后的数据)进行计算,并返回一个单一的汇总值。

函数作用示例
SUM()求和SELECT SUM(salary) FROM employees;
AVG()平均值SELECT AVG(price) FROM products;
COUNT()计数 (常用)SELECT COUNT(order_id) FROM orders;
MAX()最大值SELECT MAX(temperature) FROM readings;
MIN()最小值SELECT MIN(birth_date) FROM users;
4. 类型转换与格式化 (Casting and Formatting)

数值类型经常需要与其他类型(如字符串或日期)进行转换。

A. 显式类型转换 (Casting)

使用 :: 运算符或 CAST() 函数进行类型转换。

B. 格式化输出

使用 TO_CHAR() 函数将数值转换为特定格式的字符串,常用于报表生成。

5. 常用数学函数 (Common Math Functions)

PostgreSQL 内置了许多标准的数学函数:

函数作用示例
ROUND(x)四舍五入到最近的整数SELECT ROUND(3.5); 4
ROUND(x, d)四舍五入到 d 位小数SELECT ROUND(3.14159, 2); 3.14
CEIL(x)CEILING(x)向上取整SELECT CEIL(3.1); 4
FLOOR(x)向下取整SELECT FLOOR(3.9); 3
ABS(x)绝对值SELECT ABS(-10); 10
SIGN(x)返回值的符号 (-1, 0, 1)SELECT SIGN(-5); -1
MOD(a, b)求模(等同于 % 运算符)SELECT MOD(10, 3); 1