PostgreSQL 是一个开源的关系型数据库管理系统,是最流行的开源关系型数据库管理系统之一,具有 strong SQL 兼容性,支持 ACID 事务,以及丰富的扩展功能。
本文主要包含以下内容:
- 我为什么选择PostgreSQL
- 基于 Docker Compose 快速安装 PostgreSQL
- 登录 PostgreSQL
- PostgreSQL与MySQL常用语法差异
- PostgreSQL管理Shell工具
1.我为什么选择PostgreSQL

公众号聊天窗口发送【数据库排名】可获取最新的数据管理系统排名资料,包含关系数据库、KV存储、时序数据库、缓存数据库、文档数据库、图数据库、向量数据库、搜索数据库、列数据库等。
由于 Oracle 和 SQL Server 是商业的数据库,很多开源项目在进行关系数据库选择时会选择默认支持 MySQL 和 PostgreSQL。 MySQL由于特殊的社区发展等原因,用户逐渐向 MariaDB 和 PostgreSQL 迁移。
藏云阁很多项目如 Harbor、Gitea、Keycloak、Umami、Discourse 默认都支持使用 PostgreSQL,所以在平台建设时也就选择了 PostgreSQL。
新用户从之前熟悉的 MySQL 切换成 PostgreSQL 并不困难,这篇文章的内容虽然不多但也基本能够支撑从MySQL切换成PostgreSQL。
由于SQL标准是一样,所以在进行数据库使用时,数据的增删改查的语法差异较小。但是对于数据库管理有差异较大,新手需要重点关注,也是本文的重点。
2.基于 Docker Compose 快速安装 PostgreSQL
PostgreSQL 有多种安装方式,这里以 Docker Compose 快速安装 PostgreSQL 为例。
如果安装 Docker 受阻可以参考文章:无法访问Docker官网,国内如何合规高效安装Docker软件[最佳实践]
yaml
services:
pgsql:
image: harbor.cncfstack.com/docker.io/library/postgres:14.19
container_name: pgsql
restart: always
environment:
- POSTGRES_USER=user0001
- POSTGRES_PASSWORD=pwd0001
- POSTGRES_DB=myfirstdb
volumes:
- /etc/localtime:/etc/localtime
- /data/postgressql-data:/var/lib/postgresql/data
ports:
- "5432:5432"
deploy:
resources:
limits:
cpus: '2'
memory: 4G
PostgreSQL默认的配置基本满足使用了,我就没有挂载配置文件。如果有特殊的配置需要调整,可以添加 command 和 volumes 配置。
yaml
command: ["postgres", "-c", "config_file=/etc/postgresql/postgresql.conf"]
...
volumes:
- /data/postgresql/conf/postgresql.conf:/etc/postgresql/postgresql.conf
启动容器使用 藏云阁镜像仓库 可以快速拉取,其他版本镜像可自行查找更换。

3.登录 PostgreSQL
使用容器的方式可以很便捷的登录到PostgreSQL中,不需要在宿主机上安装任何工具。
使用如下命令修改相关的账号密码地址信息后即可登录,在退出后由于 --rm 选项也会自动清理该容器。
bash
# docker run -it --rm -e PGPASSWORD=pwd0001 --network host -v /etc/localtime:/etc/localtime harbor.cncfstack.com/docker.io/library/postgres:14.19 psql -h 127.0.0.1 -U user0001 -p 5432 -d myfirstdb
psql (14.19 (Debian 14.19-1.pgdg13+1))
Type "help" for help.
myfirstdb=#
这里看上去命令比较长,文章末尾会提供一个封装好的 Shell 脚本,方便使用。
4.PostgreSQL与MySQL常用语法差异
基础信息及系统信息查询差异
在 PostgreSQL 中,很多管理相关的命令是使用指令的格式,比较精简但不太好记,需要多动手实操加深印象。
| 功能 / 特性 | MySQL | PostgreSQL |
|---|---|---|
| 获取帮助信息 | HELP 'contents'; |
\? |
| 查看命令历史 | 不支持 | \s |
| 退出登录 | exit 或 quit 或 \q |
\q |
| 单行注释 | # 或 -- |
-- |
| 字符串引用 | 单引号 ' 或双引号 " |
只使用单引号 ' (双引号用于标识符) |
| 标识符引用 | 反引号 ````` | 双引号 " |
| 大小写敏感性 | 默认不敏感 | 默认敏感 |
| 执行外部文件 | SOURCE file_name; |
\i filename |
| 查看版本信息 | SELECT VERSION(); |
SELECT version(); |
| 查看当前用户 | SELECT USER(); |
SELECT current_user; |
| 查看所有用户 | SELECT user FROM mysql.user; |
\du 或 SELECT usename FROM pg_user; |
| 查看表空间 | SHOW VARIABLES LIKE 'datadir'; |
\db 或 SELECT * FROM pg_tablespace; |
| 查看扩展/插件 | SHOW PLUGINS; |
\dx 或 SELECT * FROM pg_extension; |
数据库相关操作差异
| 功能 / 特性 | MySQL | PostgreSQL |
|---|---|---|
| 列出所有数据库 | SHOW DATABASES; |
\l |
| 连接到数据库 | USE database_name; |
\c database_name |
| 查看当前数据库 | SELECT DATABASE(); |
SELECT current_database(); |
| 查看数据库信息 | SHOW CREATE DATABASE db_name; |
\l+ db_name |
| 查看连接信息 | SHOW PROCESSLIST; |
SELECT * FROM pg_stat_activity; |
表相关操作差异
| 功能 / 特性 | MySQL | PostgreSQL |
|---|---|---|
| 列出所有表 | SHOW TABLES; |
\dt |
| 列出所有表(含系统表) | SHOW FULL TABLES; |
\dt+ *.* |
| 查看表结构 | DESCRIBE table_name; |
\d table_name |
| 查看详细表信息 | SHOW CREATE TABLE table_name; |
\d+ table_name |
| 查看表索引 | SHOW INDEX FROM table_name; |
\d table_name |
| 查看列信息 | SHOW COLUMNS FROM table_name; |
\d table_name |
模式(Schema)相关操作差异
| 功能 / 特性 | MySQL | PostgreSQL |
|---|---|---|
| 列出所有模式 | SHOW DATABASES; |
\dn |
| 查看当前模式 | SELECT DATABASE(); |
SELECT current_schema(); |
| 切换模式 | USE database_name; |
SET search_path TO schema_name; |
功能语法差异
| 功能 / 特性 | MySQL | PostgreSQL |
|---|---|---|
| 自增主键 | AUTO_INCREMENT |
SERIAL 或 GENERATED ... AS IDENTITY (更新版本) |
| 获取最后自增值 | 3092147 |
使用 INSERT ... RETURNING id; 或 CURRVAL() |
| 分页查询 | LIMIT size OFFSET offset 或 LIMIT offset, size |
LIMIT size OFFSET offset |
| 检查 NULL 值 | IS NULL 或 IS NOT NULL (不推荐使用 = NULL) |
必须使用 IS NULL 或 IS NOT NULL (= NULL 总是返回假) |
| 正则表达式 | REGEXP |
~ (区分大小写) 或 ~* (不区分大小写) |
| 获取当前时间 | NOW() |
CURRENT_TIMESTAMP |
| 日期增减 | DATE_ADD(date, INTERVAL expr unit) |
date + INTERVAL 'expr unit' |
| IFNULL 等效函数 | IFNULL(expr, fallback) |
COALESCE(expr, fallback) |
| 类型转换 | CAST(expr AS type) 或 CONVERT(expr, type) |
CAST(expr AS type) 或 expr::type |
| 公共表表达式 | 8.0+ 版本支持 | 支持 |
| 窗口函数 | 8.0+ 版本支持 | 支持 |
| JSON 支持 | JSON 类型 (5.7+) | JSONB (二进制,性能更优) |
| GIS 支持 | 空间数据类型 | PostGIS 扩展 (功能强大) |
5.PostgreSQL管理Shell工具
在容器使用时,为了更高效的使用 PostgreSQL,可以封装一个 PostgreSQL 管理工具,方便使用。
这里是我封装的工具,一个配置文件 env 和一个脚本 pgtools.sh 文件,该脚本主要提供了4个功能:登录、创建数据库、备份数据库、恢复数据库。
bash
./pgtools.sh
Must have option,example: ./pgtools.sh login postgres
./pgtools.sh login <dbname>
./pgtools.sh createdb <dbname>
./pgtools.sh backup <dbname>
./pgtools.sh restore <dbname>
- env配置文件
env配置文件主要是一些敏感信息和动态信息,直接写死在脚本中会导致脚本的兼容性差,所以可以独立配置,方便后续修改。
bash
export PG_IP=`ip addr show eth0 |grep "inet\ "|awk -F'/' '{print $1}'|awk '{print $2}'`
export PG_PASSWORD='pwd0001'
export PG_USER=user0001
export PG_PORT=5432
- PostgreSQL 管理工具 pgtools.sh 文件
脚本中直接有一个字符串 YOUR_OSS_BUCKET 需要修改为自己的OSS存储桶名称。
在脚本准备完成后,可以添加可执行权限并将 PATH 添加到环境变量中,方便使用。
详细的脚本内容
bash
#!/bin/bash
SUBCMD=$1
DBNAME=$2
if [ $# -ne 2 ];then
echo "MUST have option,example: $0 login postgres"
echo "$0 login <dbname>"
echo "$0 createdb <dbname>"
echo "$0 backup <dbname>"
echo "$0 restore <dbname>"
exit 1
fi
source `dirname $0`/env
DATETIME=`date +%Y%m%d-%H%M%S`
BAK_DIR="/data/backup/postgresql"
if [ ! -d $BAK_DIR ];then
mkdir -p $BAK_DIR
fi
BAK_FILE=${BAK_DIR}/${DBNAME}/${DBNAME}-${PG_IP}-${DATETIME}.sql
if [ ! -d ${BAK_DIR}/${DBNAME} ];then
mkdir -p ${BAK_DIR}/${DBNAME}
fi
PGCLI_RM="docker run -it --rm -e POSTGRES_PASSWORD=$PG_PASSWORD -e PGPASSWORD=$PG_PASSWORD -v /data/backup:/data/backup -v /etc/localtime:/etc/localtime harbor.cncfstack.com/docker.io/library/postgres:14.19 "
login(){
$PGCLI_RM psql -h $PG_IP -U $PG_USER -p $PG_PORT -d $DBNAME
}
createdb(){
$PGCLI_RM createdb -h $PG_IP -U $PG_USER -p $PG_PORT $DBNAME
}
backup(){
$PGCLI_RM pg_dump -h $PG_IP -p $PG_PORT -U cygpgsql -d $DBNAME -f $BAK_FILE
ossutil cp -f $BAK_FILE oss://YOUR_OSS_BUCKET/postgresql/${DBNAME}/${DBNAME}-${PG_IP}-${DATETIME}.sql
}
restore(){
$PGCLI_RM psql -h $PG_IP -p $PG_PORT -U $PG_USER -d $DBNAME -f /data/backup/${DBNAME}.sql
}
if [ $SUBCMD = "login" ];then
login
elif [ $SUBCMD = "createdb" ];then
createdb
elif [ $SUBCMD = "backup" ];then
backup
elif [ $SUBCMD = "restore" ];then
restore
else
echo "Unkonw SUBCMD"
exit 2
fi