PostgreSQL Studio
在 VS Code 侧边栏里浏览 PostgreSQL 数据源,查看和修改表数据、表结构,在命令窗口里执行 SQL,做表结构迁移、表数据同步、表导出和数据库备份。
侧边栏顶部五个页签:
| 页签 |
做什么 |
| 数据源 |
添加 / 编辑 / 测试 PostgreSQL 连接;按需展开 数据库 → 模式 → 表 / 视图 / 函数,表下分列 / 键 / 索引;查看数据、编辑结构、查看 DDL、添加和删除库 / 模式 / 表;每个模式一个 SQL 命令窗口(可评估执行计划);实例的监控面板、会话管理、锁定管理;用户、角色组与对象权限管理 |
| 迁移 |
删除目标表,按源表一模一样地重建(结构、备注、索引),可选按主键迁移数据(可按条件只迁移部分行) |
| 同步 |
源表、目标表都已存在,按字段名称对应、按主键 upsert 数据,不改表结构 |
| 导出 |
把表结构(建表、备注、索引)和数据写成 SQL 脚本,保存到本机目录;数据按行数、文件大小自动拆成多个脚本(可按条件只导出部分行);任务下面列出每一份导出,可以一键恢复到表 |
| 备份 |
经数据库连接让服务器执行 pg_basebackup(整个实例)或 pg_dump(一个库),备份写在服务器上的目录里;任务下面列出服务器上的每一份备份,库备份可以一键恢复 |
迁移、同步、导出、备份四页都是文件夹 → 任务的树,可以单独执行一个任务,也可以按顺序执行整个文件夹;导出页、备份页的任务下面还有一层:每一份导出 / 备份。
所有配置保存在 ~/.x1/postgresql-studio/conf.yaml(见「配置文件」)。设置项、命令面板里的命令见「设置项与命令」。
数据源
添加 / 编辑数据源
「添加数据源」弹窗填写:名称、主机、端口、用户名、密码、默认数据库、SSL(disable / require / verify-full),可以先「测试连接」。默认值是 127.0.0.1 / 5432 / postgres / postgres;名称留空时取「主机:端口」。require 只加密不校验证书,verify-full 校验证书和主机名。连接超时 15 秒。
数据源右键:编辑实例、复制实例(名称加「副本」)、测试连接、删除连接,监控面板、会话管理、锁定管理(见「实例监控」),系统安全(用户与权限管理、修改密码,见「系统安全」),添加数据库、备份实例。「删除连接」只删除本地 conf.yaml 里保存的这条连接信息,不会删除服务器上的数据库和数据,以后可以重新添加;删除时会提示有几个迁移 / 同步任务引用了它,删完关掉它名下开着的数据查询页、编辑表、添加库 / 模式、删库确认、命令窗口和监控、会话、锁页、用户与权限页。编辑保存后旧连接作废,命令窗口的会话断开,树上这个数据源重新加载。
对象树
树的每一层都是展开时才查询。数据源 → 数据库 → 模式 → 「表 / 视图 / 函数」三组;表下面分「列 / 键 / 索引」三组:列是字段(主键带黄色钥匙图标,timestamp / timestamptz 字段图标为黄色,其余 NOT NULL 字段图标为蓝色,悬停看类型、默认值、备注),键是主键、唯一约束、外键,索引是表上全部索引(含主键、唯一约束背后的索引);视图下面直接列出字段。系统模式(pg_*、information_schema)、扩展自带的对象、分区表的分区、聚合和窗口函数不列出。
备注显示在名称后面:数据库的是黄色、模式的是紫色(和各自的图标同色),表、字段、键、索引的是绿色;字段有默认值的,备注后面再接「默认 …」(生成列不算)。表的行尾按钮左边显示占用空间(如 32K,含索引、TOAST,分区表是各分区合计);表悬停显示估算行数(没统计过的不显示)、占用空间和「分区表」,视图标出「物化视图」,函数标出「存储过程」或返回类型。
右键菜单和行尾按钮:
| 节点 |
右键菜单 |
行尾按钮 |
| 数据源 |
建立连接、重新连接、断开连接、编辑实例、复制实例、测试连接、删除连接、监控面板、会话管理、锁定管理、系统安全 ▸ 用户与权限管理 / 修改密码…、添加数据库、备份实例… |
刷新(鼠标移入时显示) |
| 数据库 |
复制名称、添加模式、删除数据库 |
刷新(鼠标移入时显示) |
| 模式 |
复制名称、添加表、删除模式 |
显示命令窗口、刷新 |
| 表 |
复制名称、查看数据、查看 DDL、编辑结构、构建查询 / 删除 / 更新 / 插入 / 插入(冲突检测)语句、以此为源表新建迁移任务 / 同步任务、清空数据、删除表 |
显示命令窗口、刷新 |
| 视图、函数 |
显示命令窗口、查看定义、复制名称、刷新 |
查看定义、刷新 |
| 视图的字段 |
显示命令窗口、复制名称 |
— |
| 表 / 视图 / 函数、列 / 键 / 索引这些分类节点,表下的字段、键、索引 |
— |
— |
「复制名称」:表、视图、函数复制「模式.名称」,其余复制名称本身。分类节点没有菜单和按钮:别处新建了表、视图、函数,点模式行尾的刷新就能看到,分组后面的数量也跟着更新;也可以选中某个分组按 F5 只刷新这一组,刷出了对象的空分组会自动展开;表下的分组按 F5 刷新的是表。
键盘:↑↓ 移动,←→ 收展,Enter / 空格切换收展,任何节点上 F5 刷新。双击表打开数据查询页,双击视图 / 函数查看定义,双击字段 / 键 / 索引复制名称。空白处右键「添加数据源」。
工具栏:搜索框(筛选的是已加载的节点)、全部刷新(重新读取配置文件,展开着的节点重新查询)、全部折叠、精简折叠(只收起表和视图下面的节点,上面几层保持展开),以及「更多」菜单:打开配置文件、重新加载配置、清除失效偏好、显示日志。
五个页签的工具栏排法一样:搜索框右边第一个都是「刷新」,然后是收展按钮,最后是「更多」。点「刷新」都先重新读取 conf.yaml(在别处改过、文件监听没赶上时用),结果显示在状态栏,再刷新本页:数据源页重新查询展开着的节点,导出页、备份页重新列出导出 / 备份。
连接状态
参照 DBeaver:数据源图标右下角带绿点表示已连接。展开数据源、打开命令窗口 / 监控面板等用到它时自动连接;连接池里空闲的物理连接一分钟后自动断开,下次用时补上,状态不变。右键前三项按状态启用:
- 建立连接(未连接时):连数据源的默认库,连上后展开它列出数据库;连不上就报错;
- 重新连接(已连接时):关掉这个数据源的全部连接(树和各页面用的连接池、命令窗口的会话)再连,用于网络断过、服务器重启过、连接卡住的情况;树上展开着的节点重新加载,展开状态不变;
- 断开连接(已连接时):关掉全部连接,树上收起它(再展开时重新连接)。命令窗口、监控面板等页面留着:命令窗口下次执行时重新连接,监控面板、会话 / 锁定管理停止自动刷新,「建立连接」后接着刷新。
重新连接、断开连接之前:命令窗口正在执行语句的要先停止;有没提交事务的先问「提交」还是「回滚」(出错的事务只能回滚)。迁移、同步、导出、备份任务用各自的连接,不受影响。
系统安全
用户与权限管理
右键「系统安全 ▸ 用户与权限管理」在编辑区打开一个标签页(标签名如「用户与权限 - 本地库」,同一个数据源只开一个)。参照 pgAdmin(角色对话框 + 授权向导)、DBeaver / Navicat(角色编辑器里的权限勾选表)的做法,把它们合到一个页面上:左边是角色列表,右边是选中角色的三页,下面实时预览要执行的 SQL,点「应用」(Ctrl+S)执行。
- 角色列表:列出实例的用户(能登录)和角色组(不能登录),可以按「全部 / 用户 / 角色组」分开看、按名字和备注筛选;标出当前连接用户、超级用户、密码已过期;内置角色(
pg_ 开头)勾「显示内置角色」才列。「新建用户」「新建角色组」先在页面上起草,填好后「创建」;「删除」见下面。
- 基本信息:角色名(改名)、备注(
COMMENT ON ROLE)、能不能登录、密码(两次输入;可生成随机密码;可清除密码)、有效期(永不过期或到期时间,带日期选择器)、连接数上限,以及超级用户 / 创建数据库 / 创建角色 / 继承权限 / 流复制 / 绕过行级安全六个属性开关(卡片上写着各自管什么)。ALTER ROLE … SET 设的会话参数只读列出。密码跟「修改密码」一样在本机算成验证串再发,预览、日志、报错里都写成 '********';改的是数据源用户时可以同时更新 conf.yaml 里保存的密码。
- 成员关系:「所属角色组」「成员」两张表,勾选就是加入 / 移出,逐个设 ADMIN(PostgreSQL 16 起还有 INHERIT、SET)。内置角色带中文说明,比如加入
pg_read_all_data 就是全库只读、pg_monitor 给监控用。
- 对象权限:选库、模式后,一个矩阵按「数据库 / 模式 / 表和视图 / 序列 / 函数和存储过程」分区列出对象和它们的权限(列名是关键字加中文,悬停有说明)。格子点一下授予 / 撤销,Shift+点击切换可转授(WITH GRANT OPTION);点列名整列切换,点行首整行切换;经角色组、PUBLIC 已有的权限是虚线框里的淡勾(悬停写明来源),属主那一行是灰的不能改。可以按名字筛选、「只看有权限的」。「快速授权」对当前筛选出来的对象一键授予只读(连接本库、模式 USAGE、表 SELECT、序列 SELECT)/ 读写(另加 INSERT、UPDATE、DELETE,序列 USAGE、UPDATE,函数 EXECUTE)/ 全部权限,或撤销全部;勾上「同时设置默认权限」,各模式的属主以后在里面新建的表、序列、函数也自动授予。
- 默认权限:矩阵最后三个分区是
ALTER DEFAULT PRIVILEGES——某个角色以后(在某个模式里)新建的表、序列、函数自动授予哪些权限;「添加」选创建者、模式、对象类型。
- 改动、预览与执行:页面上的改动是草稿,改过的格子、字段、成员行标出颜色,列表和页签上有小点;扩展按打开时读到的原样对比生成语句,改动相同的对象并成一条(
GRANT SELECT ON TABLE a, b, c TO r)。实例级的语句(建角色、改名、属性、密码、备注、成员关系、库的权限)在默认库一个事务执行,各库里的对象权限、默认权限各一个事务,依次执行;第一组就失败时什么都没变,草稿留着接着改。有没应用的改动时换角色、刷新会先问。PostgreSQL 16 起同一对成员关系可以有几个授予者,别人授予的那行用 GRANTED BY 撤销。
- 删除角色:先查它在各个库里拥有的对象、被授予的权限,选「把它拥有的对象转给」某个角色(
REASSIGN OWNED),或连同对象一起删除(DROP OWNED,它是某个库的属主时不能选),然后在每个库里执行,最后 DROP ROLE。当前连接用户、内置角色不能删。
函数分区不列扩展自带的函数,表分区不列分区表的各个分区(经父表访问只查父表的权限);列级权限、表空间、外部服务器等对象的权限不在这里管理,需要时在命令窗口执行。
修改密码
右键「系统安全 ▸ 修改密码…」弹出窗口(同一个数据源只开一个),列出实例里的全部用户(pg_roles,不含 pg_ 开头的内置角色),选一个,填新密码和确认密码。列表可以筛选;一行里标出当前连接用的用户、超级用户、不能登录(NOLOGIN 的角色)、密码已过期或有效期(VALID UNTIL);没有权限改的置灰不能选:超级用户改谁都行,否则只能改自己的,有 CREATEROLE 的能改不是超级用户的(PostgreSQL 16 起还要对那个角色有 ADMIN OPTION)。
密码在本机按服务器的 password_encryption(scram-sha-256 或 md5)算成验证串再发给服务器(跟 psql 的 \password 一样),ALTER ROLE … PASSWORD 语句里不含明文,服务器日志、pg_stat_statements 里也不会出现;密码里有 ASCII 可打印字符以外的字符时在本机算不准(SASLprep),退回明文由服务器加密。扩展的日志只记改了谁,不记密码。改的是数据源连接用的那个用户时,多一个「同时更新这个数据源保存的密码」勾选框(默认勾上),conf.yaml 里保存的密码跟着改,不然下次连接就连不上了;已经连着的会话不受影响,下次连接起用新密码。
查看 DDL 与定义
表的「查看 DDL」在编辑器里打开建表语句:字段、约束、备注、索引、外键,分区表带 PARTITION BY。视图、函数的「查看定义」打开 CREATE OR REPLACE VIEW … AS / CREATE MATERIALIZED VIEW / pg_get_functiondef 的输出。
构建语句
表右键「构建查询语句」「构建删除语句」「构建更新语句」「构建插入语句」「构建插入语句(冲突检测)」:按表的字段生成一条示例语句,追加到这个模式的命令窗口末尾(命令窗口没开就先打开,跟前面的内容空一行)并选中它,改好再执行。表名带模式名,名字需要时加双引号。
- 示例值按类型给:数字
0、布尔 false、文本 ''、日期 CURRENT_DATE、时间戳 now()、json / 数组 '{}'、uuid 全零……认不出的类型写 NULL;
- 查询:列出全部字段(有备注的在后面注释),
LIMIT 100,可以直接执行;
- 删除、更新:按主键定位(没有主键用第一个唯一约束;都没有时用第一个字段,并注释提醒把条件改成要处理的行)。更新的 SET 是主键、生成列、标识列以外的全部字段,每个后面注释类型和备注,用不到的删掉;
- 插入:生成列、标识列、serial 这些自动生成的字段不写(开头注释说明);有默认值的写
DEFAULT,可以为空的写 NULL,必填的给示例值;值一行一个,后面注释字段名、类型、默认值、备注;
- 插入(冲突检测):
INSERT … ON CONFLICT (主键) DO UPDATE SET 其余字段 = EXCLUDED.字段。主键(或唯一约束)的字段即使是自动生成的也写进去,标识列 GENERATED ALWAYS 时加 OVERRIDING SYSTEM VALUE;没有主键、唯一约束,或者除了它们没有别的字段时是 DO NOTHING。
数据查询页
打开与工具栏
双击表名(或右键「查看数据」)在编辑区打开数据查询页,同一张表只开一个页。以表格分页显示表内容,默认每页 10 行;表头显示类型,有备注的字段在类型下面用绿色显示备注(不会因此撑宽列,放不下的显示省略号),主键带钥匙图标,悬停看完整备注;值按数据库的文本输出原样显示,NULL 单独标出,换行显示成 ↵,单个值超过 2000 字符截断(悬停看开头);json、jsonb 字段不截断,格子里是完整的值。报错、提示条右边的 × 可以关掉它。
列宽默认按内容,最宽 360px。鼠标移到列标题的右边缘变成左右箭头,按住左右拖动调整这一列的宽度(最窄 40px,可以比 360px 宽,放不下的显示省略号),双击右边缘恢复自动宽度。调过的宽度按字段记着,翻页、重新查询、添加记录后照样,关掉查询页后恢复自动;修改窄列里的格子时,这一列临时撑开放下编辑框,改完回到调好的宽度。
上方工具栏:SELECT 按钮(展开字段勾选列表,最上面是「全部」,勾选结果在执行查询时生效,按钮上显示 * 或「已选数/总数」,一个字段都不勾不能查询)、WHERE 按钮和 ORDER BY 按钮(见下面的「查询条件和排序」)、「查询」按钮(条件行、排序行里回车也执行),右边是「添加 / 删除 / 提交 / 撤销」(见「增删改记录」)。
底部状态栏:左边显示满足条件的总条数和这页的查询耗时(鼠标悬停显示数据源 / 库 / 表),右边是首页 / 上一页 / 下一页 / 末页、每页行数(10 / 20 / 50 / 100 / 500)和「导出」。先按填写的排序,再按主键排序(没填排序就只按主键),翻页稳定。
查询在只读事务里执行,条件或排序里夹带别的语句、调用写数据的函数都会被拒绝。每页最多等 30 秒,超时提示加条件缩小范围;总行数最多统计 5 秒,超时则只能逐页翻,不能直接跳到末页。
查询条件和排序
WHERE、ORDER BY 两个按钮上显示实际参与查询的子句,点开是多行列表,每行是一个勾选框加一个输入框(写 WHERE / ORDER BY 后面的部分,行首顺手写的关键字会去掉)。敲字段名时弹出字段联想(Ctrl+Space 也可呼出,↑↓ 选择、回车 / Tab 填入、Esc 关闭,含大写字母或关键字的字段名自动加双引号)。
勾选的行拼进子句:条件只有一行时原样使用,多行时各自加括号、用 AND 连接,例如 (id > 100) AND (status = 'paid' OR status = 'done');排序按从上到下的先后用逗号连接,例如 created_at DESC, id,行尾的上移 / 下移按钮或输入框里的 Alt+↑↓ 调整先后。没勾选的行留作草稿,不参与查询但会保存,勾上即可启用。列表顶部的「全部」一键勾选或取消所有行,底部「添加条件」/「添加排序」新增一行,行尾 × 删除一行;有草稿时按钮上显示「勾选数/行数」。行里回车执行查询并收起列表,没有联想时 ↑↓ 在行间移动,Esc 或点别处收起,收起时空行自动丢掉。
选中、复制与粘贴
点格子选中它,点行号选中整行,点列标题选中整列,点左上角的 # 全选;Ctrl / ⌘ 点加选(再点一次取消,macOS 上用 ⌘),Shift 点从起点连选成方块,按住鼠标拖动也能连选;方向键移动,Shift+方向键扩大选区,Ctrl / ⌘+A 全选。新加的行只能整行选中。选中后:
- 直接敲字(包括中文输入法)或按回车 / F2,在起点格子打开编辑框,回车后写进所有选中的格子,编辑框后面标出格数;编辑框的「NULL」按钮同样作用于所有选中的格子;
- 复制(Ctrl / ⌘+C):一格时复制原值;多格时复制成制表符分隔的文字,含制表符、换行、双引号的值加双引号(Excel 的写法),NULL 为空,可以直接粘进 Excel、DataGrip。在本工具的数据页之间复制粘贴时值原样保留,NULL 还是 NULL;
- 粘贴(Ctrl / ⌘+V,跟 DataGrip 一样):剪贴板只有一个值时,写进每个选中的格子;是多行、多列的一块时,从选中区域的左上角开始往右、往下铺开,超出最后一列的丢掉,下面的行不够就自动添加新行,粘贴完选中粘贴进去的那一块。在新加的行的输入框里粘贴一块也从这一格铺开(一个值照常粘进输入框);空表点一下列标题再粘贴,从这一列开始添加新行;
- 右键菜单:「复制」「粘贴」「设为 NULL」。
文本类型写空文字是空字符串,其余类型是 NULL;布尔认 t / yes / on / 1 等写法。不能改的格子(生成列、截断的值、标记删除的行等)和 NOT NULL 却要写 NULL 的格子会跳过,报错条里说明跳过了几格、为什么。
增删改记录
点「添加」在表格末尾加一行输入框,每个显示的字段一格,格子里的灰字说明留空时写进去的是什么(自动生成 / DEFAULT / NULL / 必填);留空的格子和没显示的字段都用默认值(没有默认值为 NULL),生成列不能填。布尔字段是下拉:有默认值时第一项是 DEFAULT,NOT NULL 又没有默认值时第一项是灰掉的「必填」,然后是 true / false / null(NOT NULL 字段的 null 灰掉不能选);日期、时间戳字段点格子弹出日历(时间戳还有时、分、秒,↑↓ 加减;底部「今天 / 现在」填入当前时间,「清空」清空),点日期即填入,也可以直接在格子里敲,带时区的时间戳按本机时区填(末尾带上如 +08:00 的偏移)。表格里的布尔值显示成 true / false。
双击已有记录的格子直接修改:格子换成编辑框(布尔是只有 true / false 的下拉,日期、时间戳直接弹出日历,有换行的值是多行框),回车(多行框里 Ctrl / ⌘+回车)或点别处记下,Esc 放弃,Tab / Shift+Tab 跳到这一行下一个 / 上一个能改的格子。每个字段(包括布尔)的编辑框后面都有「NULL」按钮,点了把格子设为 NULL:可以为 NULL 的字段按钮是蓝色,NOT NULL 的灰掉不能点;清空格子时,文本类型(text、varchar、char、name、citext)存空字符串,其余类型存 NULL。改过的格子标蓝,鼠标悬停显示原值,改回原值就不算改过。表没有主键、生成列、GENERATED ALWAYS 的标识列、超过 2000 字符被截断的值(json、jsonb 不截断,能直接改)、标记删除的行不能改,双击时说明原因。带时区的时间戳在日历里按本机时间显示,选完写回的还是同一时刻。
选中格子所在的行就是选中的行,点「删除」或在表格里按 Delete 键:已有的行标成粉色,新加的行直接去掉;选中的都已标记时再删一次取消标记。点「提交」先检查必填的字段(NOT NULL 且没有默认值的标红),再在一个事务里先删、再改、后加:删除、修改按查询时的主键定位(没显示主键字段也行),修改只写改过的字段,每条必须正好删掉 / 改到一行,找不到(已被别人删除或改了主键)就报错;任何一条失败(外键、约束、类型不对、等锁超过 10 秒)整体回滚,报错里说明是第几条并在表格里标出那一行,修改都留着,改好可以再提交。提交成功后重查当前页(这页删空了就回上一页),状态栏显示新增、修改、删除了几行。「撤销」放弃所有没提交的修改。修改只在当前页上,有没提交的修改时不能执行查询、翻页、改每页行数;表没有主键时只能添加,不能修改、删除已有的行。
导出
点状态栏最右边的「导出」选格式,再选保存位置(默认文件名是 表名_insert.sql / 表名_update.sql / 表名.csv / 表名.tsv,记住上次的目录)。导出的是满足条件的全部行,不受每页行数限制;字段、条件、排序按上次执行的查询(列表里改了但没执行的不算),排序在最后再按主键排,顺序稳定。导出在只读事务里用游标分批读、边读边写文件,大表也不占多少内存;通知栏显示进度,可以取消,导出中按钮显示「导出中…」。先写到同目录的 .part 临时文件,成功后才改成选定的文件名,失败或取消不会留下半截文件,也不会覆盖原来的同名文件。完成后可以直接打开文件或所在文件夹。
- SQL INSERT:每行一条
INSERT INTO "schema"."table" (字段…) VALUES (…);,只写显示的字段。生成列不写;写入 GENERATED ALWAYS 的 identity 字段时加 OVERRIDING SYSTEM VALUE。
- SQL UPDATE:每行一条
UPDATE … SET … WHERE 主键 = …;,按主键定位,SET 显示的字段里主键、生成列、GENERATED ALWAYS identity 以外的。表没有主键时不能选。
- CSV:逗号分隔、CRLF 换行,第一行是字段名;含逗号、双引号、换行的值加双引号,NULL 写成空,空字符串写成
""。文件带 UTF-8 BOM,Excel 双击打开中文不乱码。
- TSV:规则同 CSV,分隔符换成制表符、LF 换行,不带 BOM。
SQL 文件开头有注释说明来源、条件、排序、导出时间和没导出的字段,并带一句 SET standard_conforming_strings = on;。值以数据库的无损文本输出为准:整数、numeric、浮点、布尔直接写,其余写成字符串字面量,导入时按列类型解析,时间精度、浮点、bytea、数组、json 原文都能原样导回。
用户偏好
在查询页手动执行(点「查询」或回车)且成功的查询,其显示的字段、条件行、排序行(都连同没勾选的草稿)会按「数据源 / 数据库 / 模式 / 表」自动存进 conf.yaml 的 tablePrefs,下次打开这张表自动填好并按它查询;三项都恢复成默认(全部字段、无条件、无排序)再执行一次,这张表的偏好就删掉了。数据源删除后,它名下的偏好和命令窗口的内容可在「更多」菜单里用「清除失效偏好」清掉。
表结构
编辑表
右键表名「编辑结构」(表下的字段、键、索引节点也能打开,打开时选中那一项)打开修改表结构的弹窗(仿 DataGrip 的 Modify Table)。左边是结构树:表 → 列 / 键 / 外键 / 索引 / 检查,名称后面是灰色的类型或定义,再后面是绿色的备注(和侧边栏数据源树一样,改注释时跟着变),字段有默认值的再接「默认 …」;工具栏可以新建(Alt+Insert;选中分组时加进这一组,选中表时弹菜单选种类;右键菜单也能新建)、删除(Delete)、复制一份(Ctrl+D)、上移 / 下移(Alt+↑↓);右边是选中项的属性;下面「预览」随改随显示将要执行的 SQL(Alt+P 收起 / 展开,可以在编辑器里打开)。新加的项绿色、改过的蓝色,和原来不同的输入框左边标一道颜色。左右分隔条可以拖动。
- 表:名称、注释、UNLOGGED、存储参数(
fillfactor=90, autovacuum_enabled=false)、访问方法(PG 15+)、表空间、所有者、授权(按角色勾权限,可转授即 WITH GRANT OPTION);分区键、分区边界只读;PG 11 及以前还能切换「有 OID」;
- 列:名称、注释、类型、默认值、NOT NULL、标识(GENERATED ALWAYS / BY DEFAULT AS IDENTITY)、生成表达式、排序规则。默认值、标识、生成表达式三选一。表名、字段名右边的「aB → a_b」按钮把驼峰命名转成小写下划线(UserName、userName → user_name,LevelA → level_a,Level1 → level_1,连续大写当缩写:HTTPServer → http_server),名称已经是这种写法时不可点。类型、排序规则输入时弹出下拉联想(以输入开头的在前,包含输入的在后),↑↓ 选、回车 / Tab 填入、Esc 收起,↓ 或 Ctrl+Space 列出全部。改类型时数据库不能自动转换的(比如 text 改 integer)填「类型转换」即 USING 后面的表达式;同时改了默认值的,先去掉旧默认值再改类型。已有字段加标识后,序列自动拨到现有最大值之后;已有的普通字段不能改成生成列,PG 13 起才能把生成列改回普通字段,PG 17 起才能改生成表达式。PostgreSQL 不能调整已有字段的顺序,新加的字段排在最后,只有新字段之间能上下移;新字段 NOT NULL 又没有默认值时预览里提醒;
- 键(主键 / 唯一约束):名称、注释、字段(勾选的先后就是键里的顺序)、INCLUDE(PG 11+)、可延迟;排他约束填完整的
EXCLUDE USING … 定义;
- 外键:名称、注释、字段、目标表和目标列(不勾选即引用目标表主键)、匹配方式、更新 / 删除时的动作、可延迟;
- 检查约束:名称、注释、条件表达式、NO INHERIT;
- 索引:名称、注释、唯一、NULLS NOT DISTINCT(PG 15+)、访问方法、字段或表达式(有「插入字段」下拉)、INCLUDE(PG 11+)、部分索引条件、存储参数、表空间。
名字首尾的空白会去掉;表名、字段名、约束名、索引名超过 63 字节直接列为问题(PostgreSQL 会静默截断)。约束、索引的定义改了就删掉重建(和 DataGrip 一样),只改名称、注释、索引表空间的用 RENAME / COMMENT / SET TABLESPACE。删除字段时,用到它的键、外键、索引、检查约束一并删除(数据库删字段时也会连带删除),底栏会说明删了哪些。
点「确定」(Ctrl+Enter)在一个事务里按顺序执行(先删外键、约束、索引、字段,再改字段、建约束和索引,最后改表本身、改表名),任何一条失败整体回滚,报错里带出错的那条语句,弹窗留着可以接着改。执行时等表锁最多 10 秒,有别的会话占着这张表时报错而不是一直挂着;脚本里有删除字段这种丢数据的操作时要再点一次「确认执行」;改类型、切换 UNLOGGED、换表空间这类会重写整张表的操作在预览里提示。每条语句走扩展查询协议,类型、表达式里夹带的第二条语句执行不了。没有改动时「确定」直接关闭;Esc 关闭,有改动时要在 3 秒内连按两次。执行成功后树上重新加载这张表所在的「表」分组。触发器、规则、行级安全策略、列级权限不在这里编辑。
新建表
模式右键「添加表」打开和「编辑表」同一个弹窗,初始是表名 new_table(重名时加序号)和一个 bigint 的 id 字段做主键。列、键、外键、索引、检查约束、授权的编辑方式和上面一样,另外:可以填分区键(RANGE (…)、LIST (…)、HASH (…))建分区表;字段可以随意上下移,建表时按这个顺序排列;外键的目标表可以选本表(比如 parent_id → id),改表名时跟着改;访问方法可以留默认(PG 12 起才能指定);不支持 WITH OIDS。名称和模式里已有的表、视图、序列、索引重名时直接列为问题,「确定」不能点。
执行顺序:一条 CREATE TABLE(字段、键、检查约束、外键都写在括号里)→ 表注释、字段注释、约束注释 → 索引和索引注释 → 授权 → 所有者不是当前用户时改所有者。全部在一个事务里执行,任何一条失败整体回滚。建好后树上重新加载模式和它下面的「表」分组,展开到新表并选中它。
添加数据库 / 模式
数据源右键「添加数据库」、数据库右键「添加模式」(仿 DataGrip 的 New)。弹窗下方随改随预览将要执行的 SQL,也可以在编辑器里打开;名称和已有的库、模式重名时直接列为问题,「确定」不能点(回车即确定;Esc 关闭,有改动时要在 3 秒内连按两次)。建好后树上只重新加载上一层,展开到新节点并选中它。同一个数据源只开一个「添加数据库」窗,同一个库只开一个「添加模式」窗。
- 添加数据库:名称(默认
new_database)、注释、所有者、模板、编码、表空间、区域提供者(PG 15+;选 icu 时填 ICU 区域,选 builtin 要 PG 17+)、排序规则(LC_COLLATE)、字符分类(LC_CTYPE)、连接数上限(-1 不限)、允许连接、作为模板,以及授权(CREATE / CONNECT / TEMPORARY,可转授)。模板是新库复制的来源,新库的编码、区域设置默认照搬它:template1 是默认模板,在它里面装的扩展、建的对象新库都会带上;template0 是干净的初始库,要用和模板不一样的编码、区域设置建库时只能选它;也可以选普通库,把它的全部内容复制一份(复制时不能有别的会话连着它)。下拉里每个模板都写出编码和区域设置,下面说明选中的模板是干什么的;编码、排序规则等留空的项,占位文字写出模板的实际值。填的编码、区域设置和所选模板不一样、模板又不是 template0 时,预览里会逐项提醒。CREATE DATABASE 不能放进事务,所以先单独执行,注释、授权随后在一个事务里执行;这一步失败时库已经建好,右下角会提示原因;
- 添加模式:名称(默认
new_schema,不能以 pg_ 开头)、注释、所有者(不是当前用户时写成 AUTHORIZATION)、授权(USAGE / CREATE,可转授),在一个事务里执行。
名称超过 63 字节报错。所有者就是当前用户时不写 OWNER / AUTHORIZATION;这时建出来的对象默认归当前用户所有,也不需要额外权限。
删除数据库 / 模式 / 表
右键菜单最下面(仿 DataGrip 的 Drop)。先查清楚要删的东西,在确认框里写明大小、里面有什么、谁依赖它(最多列 20 个)、有几个迁移 / 同步任务用到它,以及将要执行的语句,点确认才执行。删完关掉相关的数据查询页、编辑表窗口(删库、删模式还关掉里面的命令窗口和添加模式窗),树上去掉这个节点,重新加载上一层。
- 删除表:显示估算行数、占用空间;分区表的分区一起删除,不需要 CASCADE。有别的对象直接依赖这张表(视图、物化视图、别的表指过来的外键、继承的子表)时逐个列出,按钮变成「级联删除」(CASCADE;别的表上的外键只删约束本身,不删那张表)。间接依赖(依赖那些视图的视图)不在列表里,级联时也会一起删。确认前没查到、执行时数据库才报出来的依赖(比如用了这张表行类型的函数),会拿数据库列出的依赖再问一次要不要级联。删完重新加载「表」分组和模式;
- 删除模式:按种类数出模式里的表、视图、序列、函数、自定义类型,以及装在里面的扩展(会被整个删除)。空模式直接删;不空只能连同其中全部对象一起删(CASCADE),别的模式里依赖它们的视图、外键等也会被删除;
- 删除数据库:显示占用空间和还有几个会话连着。DROP DATABASE 不能放进事务,也不能在连着这个库的会话里执行,所以先关掉自己连这个库的连接池和命令窗口会话,再连到数据源的默认库(删的就是默认库时换 postgres、template1)执行。有别的会话连着时,PostgreSQL 13 起可以断开它们再删(WITH (FORCE)),更早的版本要先让它们断开。删的是数据源的默认库时会提示去编辑数据源换一个,否则连不上。为防误删,删库的确认是单独的弹窗:列出上面这些信息和将要执行的语句,要求在输入框里手工输入要删除的数据库名称(区分大小写,不能粘贴或拖放),和库名完全一致时「删除」按钮才能点;同一个库只开一个确认窗,确认期间数据源被删除或修改时确认窗自动关闭,按放弃处理。
删表、删模式在一个事务里执行,等表锁最多 10 秒,失败整体回滚。
清空数据
表右键「清空数据」(在「删除表」上面,仿 DataGrip 的 Truncate):清空表里的全部数据,表结构、索引、约束、授权都保留。点了先弹确认框,写明估算行数、占用空间、会一起清空的表,以及将要执行的 SQL 语句,点确认才执行:
- 继承的子表、分区表的分区一起清空(分区不单独列出);
- 有别的表用外键直接或间接引用这张表时,TRUNCATE 只能带 CASCADE:逐个列出这些表(最多列 20 个),它们的数据也会一起清空,按钮变成「级联清空」。引用自己的外键不算;
- 表(以及会一起清空的表)的字段有自增序列(serial / identity)时多一个按钮「清空并重置序列」(RESTART IDENTITY,新数据从序列的起始值、一般是 1 开始编号),两个按钮各自执行的语句都写在确认框里;不重置时接着原来的编号。
在一个事务里执行,等表锁最多 10 秒,失败整体回滚。确认前没查到、执行时数据库才报出来的外键引用,会拿数据库给出的说明再问一次要不要级联。清空后,开着的这些表的数据查询页从第一页重查,状态栏显示「表已清空」;页面上有没提交的修改时不重查,提示撤销后再查。
命令窗口
仿 DataGrip 的 query console:点树上模式、表行尾的「显示命令窗口」按钮,或在视图、函数、视图的字段上右键「显示命令窗口」,在编辑区打开这个模式的 SQL 命令窗口(标签名是 库.模式),每个模式一个,重复打开时切过去。上面是工具栏和 SQL 编辑器,下面是结果区,中间的分隔条可以拖动(键盘 ↑↓ 也行)调整高度。
编辑器与联想
编辑器显示行号,PostgreSQL 语法高亮(颜色跟编辑器主题),括号配对、自动补右括号,查找替换(Ctrl / ⌘+F),多光标、矩形选择,撤销重做,Tab 缩进。Ctrl+/(macOS 上 ⌘+/ 也行)注释 / 取消注释选中的行(行首加 -- )。
编辑区右键菜单在剪切、复制、粘贴下面有「数据拼接」「数据包装」,把选中的文本按行当成一条条数据,方便拼成 IN (…) 的列表:
- 数据拼接:每行后面加英文逗号,最后一行不加,
1 2 3 三行变成 1, 2, 3;
- 数据包装:每行先用单引号包起来再加逗号,最后一行不加,变成
'1', '2', '3';值里的单引号写成两个(O'Brien → 'O''Brien')。
空行原样留着、不算一条(选到下一行行首时末尾的空行也是);行首的缩进保留,行尾的空白去掉;行尾已有的英文逗号当分隔符先去掉,所以拼接过的再包装、重复执行结果都一样。没有选中时处理光标所在的行;矩形选择、多光标的几段连起来算。处理完选中结果,Ctrl / ⌘+Z 一次还原。
联想敲字时自动弹出(点号、:: 后面不用敲字,Ctrl+Space 随时呼出),↑↓ 选、回车填入(Tab 是缩进):
- FROM / JOIN / UPDATE / INTO / TABLE / TRUNCATE 后面是表和视图(先是命令窗口的模式,再是 public)、模式、数据库;
- SELECT / WHERE / ON / SET / ORDER BY 等后面是语句里引用的表的字段(悬停看类型、备注)、表的别名、函数,其次是表;
别名.、表名. 后面是字段,模式. 后面是这个模式里的表、视图、函数,库名. 后面是模式,模式.表. 后面是字段;
- 语句开头是 SELECT、INSERT INTO、CREATE TABLE 之类;刚写完一个名字、值后面是 WHERE、JOIN、AND、AS 之类的关键字(敲小写给小写,否则给大写);DATABASE、SCHEMA 后面是库名、模式名;
:: 后面是类型;
- 候选里显示所属模式、类型、备注;函数填入后补上括号并把光标放进去;名字含大写字母、特殊字符或是关键字时,填入时自动加双引号(在双引号里敲的连引号一起换掉);字符串、注释、数字后面不联想;
- 库、模式、表和字段第一次用到时才向数据库查,之后缓存;执行了 CREATE / ALTER / DROP / COMMENT / IMPORT 之后重新查,树上这个库(建库、删库时是整个数据源)也跟着刷新。
执行与会话
工具栏:「执行全部」(Ctrl / ⌘+Shift+Enter)执行编辑器里的全部语句;「执行选中」(Ctrl / ⌘+Enter)执行选中的部分,没有选中时执行光标所在的语句(光标在两条语句之间时,跟哪条之间没有空行就算哪条);「评估」看光标所在 / 选中的那条语句的执行计划(见下面「评估」);「停止」取消正在执行的语句,后面的不再执行。语句按分号切分,字符串、带引号的名字、注释、$$ … $$ 函数体、BEGIN ATOMIC … END 里的分号不算;逐条执行,出错即停。
每个命令窗口独占一个数据库会话,第一次执行时才连,search_path 设为这个模式(再加上 public),所以不带模式名的表先在这个模式里找。SET、临时表、没提交的事务在两次执行之间都保留;执行了 BEGIN 还没提交时,工具栏显示「事务未提交」和「提交」「回滚」按钮(事务里出错后只能回滚)。关闭窗口时会话断开,没提交的事务回滚(右下角会提示)。连接断了下次执行自动重连(会话状态随之丢失)。不支持 COPY … FROM STDIN(没有数据可给);COPY … TO STDOUT 只报行数。
事务:因为整个窗口是同一个会话,脚本里写 BEGIN; …; COMMIT; 就是真正的事务,不管是「执行全部」一次跑完,还是「执行选中」一条条执行,中间的语句都在这个事务里,执行到 COMMIT 才提交。中途有一条出错时,执行就停在那里,后面的语句连同 COMMIT 都不执行,事务变成「事务出错,只能回滚」,点「回滚」撤销前面所有的改动,不会提交一半。
工具栏「事务:自动 / 手动」切换提交方式(仿 DataGrip 的 Tx: Auto / Manual),新开的窗口默认是自动提交,设置 pgStudio.console.manualCommit 可以改成默认手动:
- 自动提交:每条语句执行完就生效;写了 BEGIN 的,到 COMMIT 才提交;
- 手动提交:每条语句执行前,会话不在事务里就自动先 BEGIN,执行完事务一直开着,工具栏显示「事务未提交」,点「提交」才真正提交,点「回滚」全部撤销。脚本里自己写的 BEGIN / COMMIT / ROLLBACK 照常起作用(COMMIT 之后的语句又会自动开始新事务)。VACUUM、CREATE / DROP DATABASE、CREATE INDEX CONCURRENTLY、ALTER SYSTEM 这些不能放进事务的语句不替它 BEGIN,执行完就生效(会话已经在事务里时 PostgreSQL 会拒绝执行,先提交或回滚)。注意:手动提交时查询也在事务里,读过的表上的锁要到提交 / 回滚才放开,别的会话改这些表的结构会一直等着,用完记得提交或回滚;
- 切换只影响之后的执行。从手动切回自动时,已经开着的事务不会替你提交,照样显示「提交」「回滚」;
- 关闭窗口、数据源「断开连接」「重新连接」时还有没提交的事务:关窗口直接回滚(右下角提示),断开、重新连接会先问提交还是回滚;
- 翻页、数总条数、导出用的是另一个只读会话,看不到这个会话里还没提交的改动。
日志与结果集
结果区的第一个页签是「日志」,后面跟着这次执行的结果集页签,再后面是评估出的执行计划页签。
- 日志:每条语句一行——时间、语句、耗时、结果(返回 / 影响了几行,或
完成:CREATE TABLE 之类),报错时写出错误码、出错位置(第几行第几列)、详情、提示、上下文,并在编辑器里标出出错的语句和位置;RAISE NOTICE 等服务端消息跟在结果后面。最多保留最近 100 条,右边有「清空日志」;点一行在编辑器里选中那条语句;
- 结果集:一次执行里返回数据的语句(SELECT、带 RETURNING 的写语句、SHOW、EXPLAIN……)各一个结果集,页签「结果 1、结果 2……」跟在「日志」后面,点开看表格(只读),页签上的 × 或鼠标中键关闭(关的是正在看的就切到旁边那个,全关掉回到日志);下一次执行返回了数据,就换成新的这一批。执行时每个结果集最多取回 500 行(设置
pgStudio.console.maxRows 可改,最多 10000);写语句的结果超过这个数时语句已经全部执行,日志里说明影响行数未知。值的显示和数据查询页一样(NULL 标出、换行 ↵、超过 2000 字符截断,json、jsonb 不截断)。点选、拖选、Shift 点选格子,点行号选整行,点表头选整列,点左上角或 Ctrl / ⌘+A 全选,Ctrl / ⌘+C 复制成制表符分隔的文本(Excel 里直接粘贴),选区、复制都只在当前这一页里。拖动表头的右边缘调整列宽、双击恢复自动宽度(跟数据查询页一样),同一个结果集翻页后照样,下一次执行的结果集重新按内容排。有结果集且没出错时自动打开最后一个结果集,否则翻到「日志」。
结果集翻页与导出
每个结果集底部有一条工具栏(跟数据查询页的状态栏一样):左边是总条数和查询耗时,右边是首页 / 上一页 / 下一页 / 末页、每页行数(10 / 20 / 50 / 100 / 500,各结果集共用,记在窗口状态里)和「导出」(CSV / TSV / SQL INSERT)。
- 全部取回了的结果集直接在取回的行里翻页;
- 没取完的查询语句(SELECT、WITH、VALUES、TABLE 开头,且语句里没有 INSERT / UPDATE / DELETE / MERGE / INTO 这些词)另开一个只读会话重新执行:先数总条数(最多数 5 秒,超时就只能逐页往后翻、不能跳到末页),翻到取回的行以外的页时把语句包成子查询加
LIMIT … OFFSET … 重新查这一页(每页最多等 30 秒)。只读事务拦住了写数据(nextval、写数据的 WITH、FOR UPDATE 都执行不了),但 pg_notify、pg_advisory_lock 这类有副作用的函数会再跑一遍;只读会话看不到命令窗口会话里的临时表和没提交的改动,没写 ORDER BY 时每次重新查的行序也可能不同;
- 不是查询的语句(带 RETURNING 的写语句、SHOW、EXPLAIN……)重新执行会再写一遍数据,只能翻取回的行;
- 导出:全部取回了(也没有被截断的值)直接写取回的行;没取完或有值被截断的查询语句另开只读会话重新执行、一批批写出全部行,通知栏显示进度、可以取消;不是查询的语句只能导出取回的行。默认文件名取目标表名或「模式_query」。SQL INSERT 写进结果集字段来自的那张表(字段都直接取自同一张表或分区表时;生成列不写,GENERATED ALWAYS 的 identity 字段带
OVERRIDING SYSTEM VALUE);字段有算出来的、来自多张表或视图的,表名写成 query_result,导入前自己改。CSV、TSV 的写法跟数据查询页的导出一样。
评估(执行计划)
工具栏「评估」(仿 DataGrip 的 Explain Plan、DBeaver 的「解释执行计划」)对光标所在的语句(选中了就是选中的那条,一次只能一条)生成执行计划,只能评估查询和增删改语句(SELECT、WITH、VALUES、TABLE、INSERT、UPDATE、DELETE、MERGE、EXECUTE)。按钮右边的箭头展开菜单选评估方式:
- 评估(EXPLAIN):直接点「评估」就是这个。只生成计划,看估算的成本和行数,不执行语句;
- 评估并实测(EXPLAIN ANALYZE):带 ANALYZE、BUFFERS,实际执行一遍,看真实的耗时、行数、循环次数和缓冲块。语句包在事务里,执行完就回滚,写语句也不会改数据(序列号、会话级 advisory 锁之类不受事务控制的副作用除外);执行期间照样占锁,大表上的写语句慎用。
评估在命令窗口自己的会话里进行,看得到 SET、临时表和没提交的改动;会话已经在事务里时用保存点包起来,评估出错也不会让那个事务变成只能回滚。评估可以「停止」;日志里记一行(总成本和估算行数,或执行耗时和实际行数),语句有错时跟执行一样标出位置。
评估出的计划在结果区开一个「计划 1、计划 2……」页签,画成一棵树:
- 节点照 EXPLAIN 文本格式的写法(
Parallel Seq Scan on orders o、Index Scan using … on …、Hash Left Join、HashAggregate……),按层缩进,有子节点的可以收起;InitPlan、SubPlan 前面标出名字;悬停看这个节点的全部属性;
- 只看计划时的列是成本、估算行数、详情;实测时是独占耗时、实际行数(每次循环)、估算行数、循环、成本、详情;
- 独占耗时(只看计划时是成本)格子里的底色条是这个节点自己(去掉子节点)占的比例,50% 以上标红、10% 以上标橙,一眼看出慢在哪;实际行数跟估算差十倍以上标黄,悬停说明差了多少(统计信息可能过时了,可以 ANALYZE 这张表);没执行到的节点写「未执行」;
- 详情列出索引条件、过滤、连接条件、排序键、分组键、过滤掉的行数、排序方式和用的内存 / 磁盘、哈希桶数、回表次数、并行进程数、缓冲块命中 / 读取;
- 上面一行是小结(总成本、估算行数,或执行耗时、规划耗时、实际行数、触发器耗时),右边「复制 JSON」把整个计划(
FORMAT JSON 的原文)复制下来,可以贴到别的执行计划可视化工具里看。
计划页签不会被下一次执行替换(执行只换结果集页签),方便对比加索引、改写语句前后的计划;最多留 10 个,再多去掉最早的。
内容自动保存
编辑器里的 SQL 每隔几秒写回 conf.yaml 的 consoles(按「数据源 / 数据库 / 模式」),执行前、关闭窗口时、Ctrl / ⌘+S 时立即写,下次打开原样恢复;清空内容就删掉这条记录。超过 1 MB 的内容不再自动保存。数据源删除后,它名下命令窗口的内容可在「更多」菜单里用「清除失效偏好」清掉。删除数据库、模式时关掉里面的命令窗口;删库前先断开命令窗口连着这个库的会话。
实例监控
数据源右键「监控面板」「会话管理」「锁定管理」,在编辑区各打开一个标签页(标签名如「监控面板 - 本地库」),同一个数据源的同一种页只开一个,重复打开时切过去。都连数据源的默认库查:pg_stat_activity、pg_stat_database、pg_locks 是整个实例的,各个库的会话、锁都在里面。不是超级用户(也没有 pg_read_all_stats 角色)时,别的用户的会话只看得到 PID、用户、库,状态和语句是空的;取消、终止别的用户的会话也要相应权限(超级用户,或 pg_signal_backend 角色、同一个用户)。编辑数据源后这些页按新的连接参数接着查,删除数据源时一起关掉。
监控面板
仿 DBeaver 的 Dashboard,三张折线图:
| 图 |
曲线 |
来源 |
| 会话 |
活动、空闲、事务中空闲、总数 |
pg_stat_activity 里的客户端会话按状态计数(不含后台进程,也不含面板自己采样用的连接) |
| 每秒事务数 |
总数、提交、回滚 |
pg_stat_database 各库的 xact_commit、xact_rollback 之和,相邻两次采样的差除以间隔(面板自己的采样每次也算一个事务) |
| 每秒块读取 |
磁盘读取、缓存命中 |
各库的 blks_read、blks_hit 之和,同样按差值算每秒多少块(一块 8 KB) |
- 工具栏:采样间隔(1 / 2 / 5 / 10 秒)、时间范围(最近 1 / 5 / 15 / 30 分钟)、暂停 / 继续、清空;右边是 PostgreSQL 版本、实例已运行多久、最近一次采样的时刻。切到别的标签页也照常采样,切回来曲线是连续的;
- 标题右边的小结:会话图是「已用 / 最大连接数」,事务图是时间范围内的平均值,块读取图是时间范围内的缓存命中率;
- 图例里一直显示每条曲线的当前值,点一下隐藏 / 显示那条曲线(纵轴按剩下的曲线重新取刻度);右上角按钮放大成整个区域,再点还原;
- 鼠标悬停显示竖线和这个时刻所有曲线的值;也可以点曲线区后用 ←→ 逐个时刻看,Home / End 到头尾,Esc 收起;
- 第一次采样只有会话数,每秒的量要等第二次。暂停后继续、采样出错、改了数据源之后,曲线从断开处另起一段;统计被重置(
pg_stat_reset)时那一个点空着,不画成负数;
- 横轴按服务器上的采样时刻画,显示成本机时间;最多保留 30 分钟。
会话管理
pg_stat_activity 每个会话一行:PID、用户、数据库、应用名称、客户端、状态、等待、持续(处在当前状态多久了)、会话开始、查询开始、语句(缩成一行,悬停看全文)。默认顺序是执行中的在前(执行得越久越靠前)、事务中空闲的其次、空闲的最后。状态前面的圆点:活动绿色、事务中空闲黄色、事务中空闲(已出错)和等锁的红色,等锁的会话在「等待」里写出被哪些 PID 阻塞。本工具查询这张列表用的连接淡色显示。
- 工具栏:刷新(F5)、自动刷新(关闭 / 2 / 5 / 10 / 30 秒,页面看不见时不查,切回来补查一次)、筛选(PID、用户、库、应用、客户端、完整语句,不分大小写,Esc 清空)、隐藏空闲、显示后台进程(autovacuum、walwriter 之类,应用名称一栏写进程类型);
- 点表头排序,升序 → 降序 → 恢复默认顺序;
- 点选、Ctrl / ⌘ 点选、Shift 点选行,↑↓ 移动,Ctrl / ⌘+A 全选,Ctrl / ⌘+C 复制选中的行(带表头、制表符分隔);
- 下面的详情区显示最后点的那行:状态和持续时长、进程类型、等待事件、被谁阻塞、会话 / 事务 / 查询开始的时刻、事务 ID、xmin,以及完整的语句(空闲的会话是它最后执行的那条),可以复制;中间的分隔条拖动(或聚焦后 ↑↓)调整高度;
- 「取消查询」(
pg_cancel_backend)取消选中会话正在执行的语句,会话保留;「终止会话」(pg_terminate_backend)断开会话,没提交的事务回滚。都会先弹框列出要处理的会话(PID、用户@库、语句开头)确认;逐个执行,没权限、会话已经不在的单独报出来,其余照常;本工具自己查询用的连接跳过。执行完自动刷新;
- 右键菜单:取消查询、终止会话、复制语句、复制 PID、复制选中的行。
锁定管理
仿 DBeaver 的 Lock Manager:每个在等锁的会话和挡住它的会话一行(用 pg_blocking_pids 找,被几个会话挡住就几行),等得久的在前。列:等待 PID、等待用户、数据库、已等待、锁类型、请求模式、对象(表名、事务 900、表的某一行……)、持有 PID、持有用户、持有者状态、持有模式、等待语句、持有语句。没有会话在等锁时显示「当前没有会话在等锁」。
- 「已等待」:PostgreSQL 14 起是开始等这把锁到现在;更早的版本没有记录,用的是语句开始执行到现在;
- 「持有模式」是持有者在同一个对象上已经拿到的锁;写着「排在前面等待」的,说明它自己也没拿到,只是排在队列前面;
- 「持有者状态」是事务中空闲时,持有语句是它最后执行的那条——常见的是应用开了事务没提交;
- 「取消等待者的查询」让等待者放弃等锁;「终止持有者」断开持有者,它的事务回滚、锁随之释放(多行挡住同一个持有者时只终止一次)。右键菜单里还有终止等待者、取消持有者的查询,以及复制等待 / 持有语句、复制选中的行。确认、权限、刷新、筛选、排序、选中、详情区都跟会话管理一样。
迁移与同步
任务文件夹
「迁移」「同步」两页的工具栏有【新建文件夹】【新建任务】两个按钮,任务都放在文件夹里;还没有文件夹时保存任务会自动新建「默认」文件夹。搜索框右边的「刷新」重新读取配置文件,在别处改了 conf.yaml 里的任务、文件夹时用。
- 单独执行:任务行上的 ▶(执行中变成「停止」);行尾还有「编辑」「删除」,双击或回车编辑,Delete 删除,执行中不能删。右键还有「复制任务」(名称加「副本」,不带执行记录)、「上移 / 下移」、「显示日志」;
- 执行文件夹:文件夹行上的 ▶,按文件夹内的顺序逐个执行。某个任务失败或被停止后,后面的任务不再执行(同一文件夹里的任务往往前后有依赖,比如先迁主表再迁明细表);结束时汇总成功几个、在哪个失败、几个未执行。迁移文件夹执行前只确认一次,列出全部会被删除重建的目标表(最多列 12 张);
- 状态:行图标区分未执行 / 执行中 / 成功 / 失败 / 已取消,悬停看上次执行的时间、行数、用时、提醒;文件夹描述显示任务数和上次执行的统计;执行时行尾显示进度百分比,右下角有可取消的进度通知,成功但有提醒时通知标黄。执行中可以停止单个任务,也可以停止整个文件夹;文件夹在执行时里面的任务不能再单独执行;确认框开着时再点一次「执行」也会被挡住;
- 调整顺序:拖动任务(文件夹内排序或拖进别的文件夹)、拖动文件夹;右键菜单的「上移 / 下移」;或在「编辑文件夹」弹窗里排执行顺序;
- 复制文件夹:文件夹行上的复制按钮(或右键菜单):
- 「复制文件夹」:在同一页复制一份,名称加「副本」(重名时再加序号),排在原文件夹后面;
- 「复制到同步… / 复制到迁移…」:把文件夹里的任务配置复制到另一页,可以新建同名文件夹(重名时加序号),也可以添加到已有文件夹(源表、目标表都相同的任务跳过)。源表、目标表、任务名、每批行数、条件(同步条件 ⇄ 迁移条件)照搬,执行记录不带;迁移专有的选项(字段顺序、是否迁数据、外键)复制到同步时去掉,复制到迁移时取默认值。复制完自动切到目标页并选中文件夹;
- 删除文件夹(右键):连同里面的任务一起删,有任务在执行时不能删。
新建任务
迁移、同步两页的文件夹行上都有两个新建按钮(右键菜单、工具栏【新建任务】的下拉菜单、空白处右键菜单里也是这两项),任务放进这个文件夹;任务表单里也可以改「所属文件夹」:
- 批量任务(列表加号图标):源表是勾选列表(可筛选、全选),勾几张都按批量创建——每张表建一个任务,任务名、目标表名都取表名,按表名列表的顺序放进文件夹(这也是执行文件夹时的顺序,不记勾选先后),文件夹里已有同样源表和目标表的任务跳过。迁移不逐表检查(目标表不存在就新建、已存在就删除重建);同步会逐表列出检查结果(目标模式里有没有同名表、字段按名称对应、主键、同步条件),有不合格的表就不让创建;源和目标是同一个模式时不能创建(同名表就是同一张表);迁移勾了分区表也不能创建。迁移的字段按源表顺序(建好后可以逐个编辑调整);
- 单表任务(加号图标):源表是下拉框,只能选一张;可以改任务名(留空取源表名)、目标表。迁移可以调整迁移后的字段顺序、写迁移条件、预览 SQL;同步的目标表可以不同名,显示按名称对应的字段映射。数据源树上表的右键「以此为源表新建迁移任务 / 同步任务」也是单表任务。
表单里每批行数 1–50000,默认 1000。同一数据源,或主机、端口相同的两个数据源指向同一张表,都算「源表与目标表相同」,不能保存。任务弹窗只管配置:「保存 / 创建」(回车也是)保存后关窗,没有「保存并执行 / 创建并执行」,任务在任务列表里执行(任务行尾的执行按钮,或执行整个文件夹)。同步条件、迁移条件写错时标红提示,但照样能保存;执行时会先校验条件,在动数据之前报错(迁移在删除目标表之前)。没有数据源时打开任务表单会提示先去添加。
迁移
单表任务弹窗里选源表和目标表(数据源 → 数据库 → 模式 → 表),目标表名可以手填(下拉提示已有的表),不存在就新建。字段顺序:列出源表全部字段,拖动或用箭头(Alt+↑↓)调整目标表中的字段顺序,「恢复源表顺序」一键还原。字段名不变,按名称一一对应;之后源表新增的字段排在末尾。「预览 SQL」浮层可以复制或在编辑器里打开将要执行的完整脚本,不改动任何东西。
迁移条件(可选,单表任务和编辑任务时可写,批量任务不带):只迁移源表中满足条件的行,写法、字段联想、「检查条件」、大小写提示和安全措施都与同步条件相同,例如 "flagDelete" = false、created_at >= '2026-01-01'。
- 只影响数据:表结构、备注、索引照常完整重建,目标表里只有满足条件的行;
- 只在勾选「迁移数据」时生效;不勾时条件框置灰,内容保留;
- 执行前先在源表上校验条件,写错了在删除目标表之前就报错,目标表保持原样;预览 SQL 时也会校验,并在脚本里写明条件;
- 序列照常校准到不小于源序列当前值,之后在目标库插入不会撞上没迁过来的 id。
执行步骤:
- 读取源表定义(源库会话只读);有迁移条件时先校验条件;
- 目标库一个事务内(等表锁最多 30 秒):
DROP TABLE IF EXISTS 目标表,按源表定义建表(字段类型、排序规则、默认值、NOT NULL、identity、生成列、主键 / 唯一 / 排他 / 检查约束、UNLOGGED、存储参数;serial 字段在目标模式新建同参数的序列并 OWNED BY;检查约束的 NOT VALID 去掉),写表备注、字段备注、约束备注,再创建普通索引(含表达式索引、部分索引、INCLUDE)并写索引备注。先建索引,后插入数据:结构一次性完整落地,这一步任何地方失败都会整体回滚,目标表保持原样;
- 勾选「迁移数据」时分批写入(有迁移条件时只读满足条件的行),写入时所有索引(含唯一索引)都已生效:源表有主键时按主键分批
INSERT … ON CONFLICT (主键) DO UPDATE;没有主键时用游标按物理顺序读、直接 INSERT;
- 校准 serial / identity 序列:不小于源序列当前值和导入数据的最大值;
- 勾选「迁移外键约束」时补建外键(引用的表须已存在于目标库,建不上只提示不中断);自引用外键指向新表。外键放在数据之后,因为自引用的父行不一定先导入。不勾时每个外键作为提醒列出;
ANALYZE 目标表。
索引、约束、序列名里含源表名的,会换成目标表名(users_pkey → users_bak_pkey;只换整段,表叫 t 时 created_at_idx 不动),与目标模式里已有的名字重复时加 _1 后缀。执行前默认弹窗确认(设置 pgStudio.migration.confirmBeforeRun 可关闭)。
同步
源表、目标表都要已存在。字段严格按名称对应(区分大小写),两边字段顺序不同不影响:
- 两边都有的字段:同步;类型写法不同时按目标类型转换,转换失败(例如目标字段更短)会报错,不会静默截断;
- 只有目标表有的字段:不写入(新行取默认值,已有行保持原值);NOT NULL 又没有默认值的在表单里警告;
- 只有源表有的字段:忽略;
- 目标表的生成列:由目标库计算;目标表 GENERATED ALWAYS 的 identity 字段不参与更新,写入时带
OVERRIDING SYSTEM VALUE。
冲突键是目标表的主键(必须在源表中有同名字段,目标表没有主键不能同步),INSERT … ON CONFLICT (主键) DO UPDATE。源表没有主键时用游标按物理顺序读。同步结束后把目标表的 serial / identity 序列拨到不小于最大值,避免之后在目标库插入时撞主键。表单里会预览字段映射、冲突键和问题提示。
同步条件(可选):只同步源表中满足条件的行,写 WHERE 后面的部分,例如 "flagDelete" = false、updated_at >= now() - interval '7 days' AND status <> 'draft'。
- PostgreSQL 会把不加引号的字段名转成小写:字段名含大写字母(建表时加了引号)的,条件里也要加双引号。写错时会提示正确写法;
- 字段联想(单表任务、编辑任务时):条件框里敲字段名时弹出源表的字段(显示类型和备注),跟数据查询页的条件行一样:Ctrl+Space 也可呼出,↑↓ 选择、回车 / Tab 填入、Esc 关闭,含大写字母或关键字的字段名自动加双引号;可以跨行写,联想框贴着正在输入的那一行;字符串、
-- 注释里不联想。批量任务的条件作用于多张表,不联想;
- 表单里「检查条件」会在源表上校验,并报出满足条件的行数(数超过 5 秒只报条件有效);
- 执行前先校验条件,写错了在写入任何数据之前就报错;
- 条件只决定读哪些源行:源表里后来不再满足条件的行(比如
flagDelete 改成了 true),目标表里已有的那行不会被删除或更新;
- 安全:带条件的查询一律走扩展查询协议(一次只能执行一条语句,夹带
; DROP … 会被拒绝),源库会话设为只读(条件里调用会写数据的函数也写不进去)。
数据传输
迁移、同步共用的读写方式:
- 读:有主键时按主键 keyset 分页(
WHERE (pk) > (上一批末行) ORDER BY pk LIMIT n),每批一条独立语句,不在源库挂长事务;没有主键时用只读事务里的游标;
- 写:每批一条
INSERT … SELECT … FROM unnest($1::text[], $2::text[], …) ON CONFLICT …,参数个数等于字段数,和行数无关;
- 所有值以 PostgreSQL 的文本格式原样往返(会话固定
DateStyle = 'ISO, YMD'、IntervalStyle = postgres、extra_float_digits = 3、bytea_output = hex、standard_conforming_strings = on、client_encoding = UTF8、statement_timeout = 0),浮点极值、时间戳微秒、numeric、bytea、数组、json 原文都不经过 JS 类型转换;
- 读下一批和写当前批并行进行;进度的总行数取统计信息的估算值(超过 500 万行或带条件的大表不精确数);
- 执行中可以在通知或列表行上停止,每一步写进「输出 → PostgreSQL Studio」。
导出
「导出」页跟「迁移」页的用法一样:工具栏【新建文件夹】【新建任务】,文件夹行上有批量任务、单表任务两个新建按钮,可以单独执行一个任务,也可以按顺序执行整个文件夹;拖动排序、上移下移、编辑文件夹、复制任务、复制文件夹、删除也都一样(见任务文件夹)。不同的是:
- 一个任务一张表,没有目标表,换成「保存位置」:
- 保存路径:本机目录,绝对路径,可以
~ 开头;【选择…】弹出系统的选目录框。新建任务时预填所在文件夹里最近一个任务的保存路径;
- 每个数据文件最多行数(默认 100000)、每个数据文件最大 MB(默认 50):数据超过任何一个就拆到下一个文件,先到哪个算哪个;0 表示不限,两个都是 0 时数据只有一个文件。单独一行就超过大小上限的,自己一个文件;
- 导出条件(可选,单表任务和编辑任务时可写,批量任务不带):只导出源表中满足条件的行,写法、字段联想、「检查条件」、大小写提示和安全措施都与同步条件相同。只影响数据,表结构照常完整导出;
- 批量任务按源表勾选,任务名取表名;文件夹里已有同样源表和保存路径的任务跳过;勾了分区表不能创建;
- 文件夹只能在导出页里复制(导出没有目标表,不能复制到迁移、同步,反过来也不行);
- 导出不改动任何数据,执行前不弹确认框。数据源树上表的右键「以此为源表新建导出任务」也能新建(单表任务)。
每次执行都重新导出一份,放在「保存路径 / 模式.表名」下以执行时间命名的新目录里(同一秒里再执行加 _2、_3),旧的导出不动、不自动清理:
~/pg-export/
└── public.orders/
├── 20261011_093000/
│ ├── schema.sql 表结构
│ ├── data_0001.sql 数据,第 1 个文件
│ ├── data_0002.sql 数据,第 2 个文件……
│ ├── foreign_keys.sql 外键(表有外键时才有)
│ └── restore.sql 用 psql 一键恢复
└── 20261012_093000/
- schema.sql:一个事务里建序列、建表(字段类型、排序规则、默认值、NOT NULL、identity、生成列、主键 / 唯一 / 排他 / 检查约束、UNLOGGED、存储参数),写表备注、字段备注、约束备注,建普通索引(含表达式索引、部分索引、INCLUDE)并写索引备注,最后把 serial / identity 序列拨到导出时的当前值(没有序列读取权限时跳过并提醒)。建表语句和迁移用的是同一套;
CREATE SCHEMA、DROP TABLE IF EXISTS 写成注释,需要时取消注释;
- data_0001.sql……:每行一条
INSERT,有主键时按主键排序,没有主键按物理顺序;生成列不写,GENERATED ALWAYS 的 identity 字段带 OVERRIDING SYSTEM VALUE。值的写法和数据查询页导出 INSERT 一样,按 PostgreSQL 的文本格式原样写出(时间戳微秒、浮点极值、numeric、bytea、数组、json 都无损)。每个文件开头设好 client_encoding、standard_conforming_strings,整个文件是一个事务,出错整体回滚;
- foreign_keys.sql:外键及其备注。引用的表可能还没恢复、数据也可能只导出了一部分,所以单独放在数据之后执行;
- restore.sql:psql 一键恢复,
\set ON_ERROR_STOP on 后用 \ir 按顺序执行上面的文件,并注明每个数据文件的行数:psql -h 主机 -U 用户 -d 数据库 -f restore.sql(在哪个目录执行都行)。目标库里不能已有同名表。不用 psql 时,按 schema.sql → data_0001.sql、data_0002.sql…… → foreign_keys.sql 的顺序逐个执行即可(命令窗口也能执行这些文件的内容)。
执行时:源库会话只读,在一个 REPEATABLE READ 只读事务里读表结构、序列当前值和数据,导出的是同一时刻的快照;数据用游标一批批读(「每批行数」),读一批写一批,不把整张表放进内存。有导出条件时先校验,写错了在写任何文件之前就报错。先写进同名加 .partial 的临时目录,全部写完再改名;失败或取消时删掉临时目录,保存路径里只留完整的导出。完成后通知上有【打开目录】,在系统的文件管理器里选中这次的导出目录;任务右键「打开保存目录」选中最近一次的导出。上次执行的保存位置记在任务的悬停提示里。
导出列表与恢复
有导出的任务行前面有展开箭头(描述里写着「N 份导出」),点一下展开,下一级是这张表在保存路径里的每一份导出,新的在前:显示导出时间、行数、数据文件个数、大小,只导出了部分行的标「部分数据」;悬停看目录、来源、条件。任务默认收着;导出完成后列表自动更新,在文件管理器里删了、拷进来的,点工具栏的刷新按钮重新列(同时重新读取配置文件)。
导出行上的按钮(右键菜单里也有,外加「复制路径」):
- 恢复:恢复到这个任务的源表(导出从哪张表来就恢复到哪张表)。先检查导出是否完整(
restore.sql 列出的文件都在)、建的是不是这张表,再弹窗确认(写明数据源、库、表,哪份导出、多少行,部分数据的导出写明条件)。执行时一个事务里:DROP TABLE 原表(等表锁最多 30 秒)→ 执行 schema.sql(建表、备注、索引、序列当前值)→ 按 restore.sql 的顺序导入数据文件 → 序列校准到不小于数据的最大值 → 执行 foreign_keys.sql(每个外键一个保存点,建不上只提醒)→ 提交、ANALYZE。失败或取消时整体回滚,表保持恢复前的样子;恢复期间这张表被锁住。数据文件一段段读、多条 INSERT 拼成一次往返(每次最多 1000 条或 1 MB),大文件不会整个读进内存;脚本里的 BEGIN / COMMIT 跳过,事务由插件管。执行顺序跟用 psql 执行 restore.sql 一样;进度显示在导出行和右下角的通知上,可以停止;
- 打开目录:在系统的文件管理器里选中这份导出的目录;
- 删除导出:确认后把整个目录移到废纸篓(回收站),需要时还能找回。正在从它恢复时不能删。
同一个任务的导出和恢复不能同时进行,所在的文件夹在执行时也不能恢复。别的表的外键、视图依赖这张表时删不掉,恢复会报错并列出依赖的对象(先删掉依赖,恢复后再建回去);目标库里没有这个模式时也会报错。
备份
「备份」页在数据库服务器上做备份:插件经数据库连接让服务器自己执行 pg_basebackup / pg_dump(PostgreSQL 的 COPY … TO PROGRAM),备份文件写在服务器(Docker 部署时是容器)里的目录,跟 VS Code 在哪台机器上无关。用法跟其他几页一样:文件夹 → 任务,工具栏【新建文件夹】【新建任务】,可以单独执行一个任务,也可以按顺序执行整个文件夹;拖动排序、编辑文件夹、复制任务、复制文件夹(只能在本页复制)、删除也都一样。
两种任务(文件夹行上两个新建按钮,工具栏【新建任务】的下拉、空白处右键也是这两项;数据源右键「备份实例…」、数据库右键「备份此数据库…」直接新建并预选好):
|
实例备份 |
数据库备份 |
| 程序 |
pg_basebackup -X stream --checkpoint=fast |
pg_dump -Fc(custom 格式,压缩) |
| 范围 |
整个实例:全部库、角色、配置 |
一个库的全部对象和数据;不含角色、表空间这类实例级的对象 |
| 产物 |
data/ 一个完整的数据目录 |
database.dump |
| 恢复 |
要停库、替换数据目录,只能在服务器上操作,插件里不能恢复 |
插件里一键恢复(见下) |
新建数据库备份时可以一次勾选多个库,每个库一个任务(任务名取库名,文件夹里已有同样数据源、库、服务器目录的跳过)。
服务器目录:数据库服务器上的绝对路径(不是本机的),默认 /var/lib/postgresql/backup,新建时预填所在文件夹里最近一个任务的。每次执行在「服务器目录 / instance 或 db-库名」下新建一个以执行时间命名的目录(同一秒里再执行加 _2),里面是备份、backup.log(程序的日志)、done(退出码和大小);旧的不动、不自动清理。用 Docker 时请确认这个目录挂载到了宿主机上(docker inspect 看 Mounts),不然重建容器后备份就没了。任务弹窗的【检查服务器】会检查:当前用户是不是超级用户、备份程序在哪儿、目录能不能写(会建出这个目录)、所在磁盘还剩多少空间。
要求:数据源的账号是超级用户(要在服务器上执行程序、读写服务器上的文件);备份程序用服务器自己的那一份(pg_config 的 BINDIR,版本跟服务器一致),经服务器本机的 unix socket 连回来,要求本机连接免密(trust / peer,官方 Docker 镜像默认如此);实例备份还要能建复制连接(默认配置可以)。
执行:
- 作业在执行
COPY … TO PROGRAM 的那个数据库后端底下同步跑完(这条连接一直等着,不放到后台:放到后台的话作业会变成孤儿,Docker 里被 1 号进程 postmaster 收养,退出时会被当成后端崩溃);另开一条连接每 2 秒查一次进度,日志的新内容转到「输出 → PostgreSQL Studio」;
- 进度:实例备份显示阶段和已传 / 总大小(PG 13 及以上);数据库备份显示已写多大、正在导出哪张表;
- 先写在
<执行时间>.partial 里,成功后改名;失败时把日志末尾报出来,删掉临时目录;
- 可以停止:结束作业的数据库连接,程序出错退出,按取消收尾;
- 备份在服务器上进行,关掉 VS Code 也会完成,下次打开列表里就有。
备份列表与恢复
有备份的任务能展开,下一级是服务器目录里这个任务的每一份备份,新的在前:显示备份时间、大小、最近一次从它恢复的时间;悬停看服务器上的路径、全部恢复记录。列表经数据库连接去读(要超级用户),读取中、读不出来(比如账号不是超级用户)时下一级是一行说明。执行、恢复结束后自动更新,在服务器上删了、拷进来的,点工具栏的刷新按钮重新列(同时重新读取配置文件)。
备份行上的按钮(右键菜单里也有,外加「复制路径」):
- 恢复(只有数据库备份):弹窗确认后在服务器上执行
pg_restore --clean --if-exists --single-transaction:一个事务里,备份里有的表、视图、函数等对象先删除再按备份重建,数据恢复成备份时的样子;备份之后新建的对象保留。失败或取消时整体回滚,库保持原样。恢复期间涉及的表被锁住,正在使用这个库的连接可能要等;等锁超过 60 秒就放弃(失败、库不变)。日志写在备份目录里 restore-<时间>.log,留作记录;
- 查看日志:备份日志和从它恢复的日志,在编辑器里打开;
- 删除备份:确认后把服务器上的整个目录删掉(不能找回)。正在从它恢复时不能删。
同一个任务的备份和恢复不能同时进行,所在的文件夹在执行时也不能恢复。
设置项与命令
设置(pgStudio.*):
| 设置项 |
默认 |
说明 |
ui.dialogWindow |
float |
数据源、任务、文件夹、编辑表、添加库 / 模式、删库确认这些弹窗在独立窗口(float)还是编辑器标签页(tab)里打开。独立窗口一律自动开启紧密模式(窗口右上角的「启用紧密模式」按钮,只留标题栏,没有标签栏和状态栏;再点一次按钮可以退出。较早的 VS Code 没有这个按钮,窗口照常打开) |
migration.confirmBeforeRun |
true |
执行迁移任务前弹窗确认(迁移会先删除目标表) |
console.maxRows |
500 |
命令窗口执行时每个结果集最多取回的行数(1–10000) |
命令面板(分类「PostgreSQL Studio」):添加数据源、添加迁移任务、添加同步任务、添加导出任务、添加备份任务、打开配置文件 conf.yaml、重新加载配置、显示日志。
配置文件
~/.x1/postgresql-studio/conf.yaml(目录 0700、文件 0600,密码为明文):
version: 3
datasources:
- id: 3f2a9c1b7e04
name: 本地开发库
host: 127.0.0.1
port: 5432
user: postgres
password: secret # 纯数字的密码要加引号,不然会被 YAML 当成数字
database: postgres
ssl: disable # disable | require | verify-full
migrations: # 文件夹 → 任务;tasks 的顺序就是执行文件夹时的顺序
- id: 5c6d7e8f9a0b
name: 用户数据
tasks:
- id: 9b1c2d3e4f50
name: users → users_bak
source: { datasourceId: 3f2a9c1b7e04, database: app, schema: public, table: users }
target: { datasourceId: 3f2a9c1b7e04, database: app, schema: archive, table: users_bak }
columnOrder: [id, name, email, created_at]
migrateData: true
where: '"flagDelete" = false' # 可选:迁移条件,只迁移满足条件的行
includeForeignKeys: false
batchSize: 1000
lastRun: { at: '2026-09-23T12:00:00.000Z', status: success, rows: 2480, durationMs: 1830 }
syncs:
- id: 1a2b3c4d5e6f
name: 报表
tasks:
- id: 0a1b2c3d4e5f
name: orders 同步
source: { datasourceId: 3f2a9c1b7e04, database: app, schema: public, table: orders }
target: { datasourceId: 3f2a9c1b7e04, database: report, schema: public, table: orders }
where: '"flagDelete" = false' # 可选:同步条件
batchSize: 1000
exports: # 导出(本机);一个导出文件夹都没有时不写这个键
- id: 6d7e8f9a0b1c
name: 每日导出
tasks:
- id: 2b3c4d5e6f70
name: orders
source: { datasourceId: 3f2a9c1b7e04, database: app, schema: public, table: orders }
outputDir: ~/pg-export # 保存路径(本机)
rowsPerFile: 100000 # 每个数据文件最多行数,0 不限
mbPerFile: 50 # 每个数据文件最大 MB,0 不限
where: '"flagDelete" = false' # 可选:导出条件
batchSize: 1000
backups: # 备份(服务器端);一个备份文件夹都没有时不写这个键
- id: 7e8f9a0b1c2d
name: 每晚
tasks:
- id: 3c4d5e6f7081
name: app
datasourceId: 3f2a9c1b7e04
scope: database # database 库备份(pg_dump)| instance 实例备份(pg_basebackup)
database: app # 库备份才有
serverDir: /var/lib/postgresql/backup # 数据库服务器上的目录
tablePrefs: # 数据查询页的用户偏好:每张表上次执行查询时的显示字段、条件行、排序行
- datasourceId: 3f2a9c1b7e04
database: app
schema: public
table: orders
select: [id, status, amount] # 不写表示全部字段
conditions: # WHERE 条件行,按显示顺序,勾选的用 AND 拼接
- text: status = 'paid'
enabled: true
- text: amount > 1000 # enabled: false 是草稿,不参与查询;一行也可以直接写字符串,算勾选
enabled: false
sorts: # ORDER BY 排序行,从上到下就是排序的先后,勾选的用逗号拼接
- text: created_at DESC
enabled: true
consoles: # 命令窗口的内容:每个模式一份
- datasourceId: 3f2a9c1b7e04
database: app
schema: public
sql: |
SELECT * FROM orders WHERE status = 'paid';
-- 草稿
UPDATE orders SET status = 'done' WHERE id = 1;
可以手工编辑,保存后插件自动重新读取(等 300 毫秒没有新改动再读,免得读到写了一半的文件;或在「更多」菜单里「重新加载配置」)。写回时先写临时文件再改名,不会留下半截文件;exports、backups、tablePrefs、consoles 为空时不写;不认识的顶层键原样保留。数据源缺 name 取主机名,缺 port / user / database 取默认值;缺必填字段的条目忽略并记进日志。无法解析的文件会被改名为 conf.yaml.broken-<时间>,不会被覆盖。
早期版本(version: 1)的 migrations / syncs 是平铺的任务列表,读取时自动归入「默认」文件夹,下次保存即写成上面的两层格式。更早的 tablePrefs 只有 where、orderBy 两个字符串,读取时各当作一行勾选的条件、排序,下次保存即写成 conditions、sorts。version: 2 的开发版把导出任务存在 backups 键下(那时「导出」页叫「备份」):版本 2 及以前的文件里没有 exports、只有 backups 时,读成导出任务,下次保存即写成版本 3。
限制
- 支持 PostgreSQL 10 及以上;
- 分区表不能作为迁移源、不能导出(同步可以;数据库备份里照常包含);
- 导出只能恢复到原来那张表(同一数据源、库、模式、表名);被别的表的外键、视图依赖的表不能恢复(要先删掉依赖);
- 备份(服务器端)要超级用户,服务器本机连接要免密;实例备份只能在服务器上恢复;数据库备份只能恢复到原来那个库;
- 字段用到的自定义类型(枚举、复合类型、域)须已存在于目标库;
- 表的属主、权限、触发器、规则、行级安全策略不迁移、不导出(数据库备份里都有);
- 浏览用的连接每个库最多 3 条,空闲 60 秒断开(监控面板、会话管理、锁定管理也用数据源默认库的这组连接);迁移、同步、导出、备份、命令窗口各自另开连接。
开发
npm install
npm run compile # 开发构建
npm run watch # 监听构建(F5 调试用)
npm run check-types # 类型检查(扩展 + webview)
npm test # 配置存储 + SQL 切分与联想、导出格式 + 导出引擎 + 备份引擎(假服务器,作业脚本用 dash 真跑)+ 密码 / 用户与权限的语句生成 + webview 前端
npm run package # 类型检查 + 生产构建
./build.sh # 打包 VSIX(也可以 npm run vsix)
npm run dev:link # 把本仓库软链到 ~/.vscode/extensions,重载窗口即生效(dev:unlink / dev:status / dev:check)
python3 scripts/render-icon.py # 改了 media/icon.svg 后重新生成 media/icon.png(仅 macOS,借用无头 Google Chrome 渲染)