postgresql-psql by timelessco/recollect
npx skills add https://github.com/timelessco/recollect --skill postgresql-psqlPostgreSQL psql(PostgreSQL 交互式终端)是用于与 PostgreSQL 数据库交互的主要命令行客户端。它既提供交互式查询执行,也提供用于数据库管理和管理的强大脚本功能。
在以下情况下使用此技能:
\dt、\d)广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
psql [OPTIONS] [DBNAME [USERNAME]]
# 使用用户名和主机连接
psql -U username -h hostname -p 5432 -d database_name
# 使用连接字符串连接
psql postgresql://username:password@hostname:5432/database_name
# 使用密码提示连接
psql -U postgres -h localhost -W
# 连接到本地机器的特定数据库
psql -d myapp_development
# 环境变量(替代方法)
export PGUSER=postgres
export PGPASSWORD=mypassword
export PGHOST=localhost
export PGPORT=5432
export PGDATABASE=mydb
psql
标准 URI 格式:
postgresql://[user[:password]@][netloc][:port][/dbname][?param1=value1&...]
示例:
postgresql://app_user:secretpass@db.example.com:5432/production_db?sslmode=require
密码文件 (.pgpass):
# ~/.pgpass (chmod 600)
hostname:port:database:username:password
localhost:5432:mydb:postgres:mypassword
*.example.com:5432:*:appuser:apppass
通过 SSH 隧道连接:
ssh -L 5432:localhost:5432 user@remote-host
psql -U postgres -h localhost
# 要求 SSL
psql -h hostname -sslmode require -U username database
# 验证证书
psql -h hostname -sslmode verify-full \
-sslcert=/path/to/client-cert.crt \
-sslkey=/path/to/client-key.key \
-sslrootcert=/path/to/ca-cert.crt database
# SSL 模式:disable, allow, prefer (默认), require, verify-ca, verify-full
\l or \list # 列出所有数据库
\l+ or \list+ # 列出数据库及其大小
\c or \connect DATABASE USER # 连接到不同的数据库
\dn or \dn+ # 列出模式(命名空间)
\dt or \dt+ # 列出当前模式中的表
\di or \di+ # 列出索引
\dv or \dv+ # 列出视图
\dm or \dm+ # 列出物化视图
\ds or \ds+ # 列出序列
\df or \df+ # 列出函数/过程
\da or \da+ # 列出聚合函数
\dT or \dT+ # 列出数据类型
\dF or \dF+ # 列出文本搜索配置
\d or \d NAME # 描述表、视图、索引、序列或函数
\d+ or \d+ NAME # 带有详细信息的扩展描述
\da PATTERN # 列出与模式匹配的聚合函数
\db or \db+ # 列出表空间
\dc or \dc+ # 列出字符集编码
\dC or \dC+ # 列出类型转换
\dd or \dd+ # 列出对象描述/注释
\dD or \dD+ # 列出域
\de or \de+ # 列出外部数据包装器
\dE or \dE+ # 列出外部服务器
\dF or \dF+ # 列出文本搜索配置
\dFd or \dFd+ # 列出文本搜索字典
\dFp or \dFp+ # 列出文本搜索解析器
\dFt or \dFt+ # 列出文本搜索模板
\dg or \dg+ # 列出数据库角色/用户
\dl or \dl+ # 列出大对象(同 \lo_list)
\dL or \dL+ # 列出过程语言
\dO or \dO+ # 列出排序规则
\dp or \dp+ # 列出表访问权限
\dRp or \dRp+ # 列出复制源
\dRs or \dRs+ # 列出复制订阅
\ds or \ds+ # 列出序列
\dt or \dt+ # 列出表
\dU or \dU+ # 列出用户映射
\du or \du+ # 列出角色
\dv or \dv+ # 列出视图
\dx or \dx+ # 列出扩展
\dX or \dX+ # 列出扩展统计信息
\a # 在对齐和不对齐输出之间切换
\C [STRING] # 设置表标题
\f [STRING] # 为不对齐输出设置字段分隔符
\H # 切换 HTML 输出模式
\pset OPTION [VALUE] # 设置输出选项(详见下文)
\t [on|off] # 切换仅元组输出(无页眉/页脚)
\T [STRING] # 设置 HTML 表格标签属性
\x or \x [on|off|auto] # 切换扩展/垂直输出
\g or \g [FILENAME|COMMAND] # 执行查询并将输出发送到文件/命令
\pset border [0-2] # 设置边框显示(0=无,1=ascii,2=unicode)
\pset columns WIDTH # 设置列宽限制
\pset csv # 设置 CSV 输出格式
\pset expanded [on|off|auto] # 切换扩展输出
\pset fieldsep STRING # 设置字段分隔符
\pset footer [on|off] # 切换页脚显示
\pset format [aligned|unaligned|csv|tsv|html|latex|latex-longtable|troff-ms]
\pset header [on|off] # 切换页眉显示
\pset linestyle [ascii|old-ascii|unicode] # 设置线条绘制样式
\pset null STRING # 设置表示 NULL 的字符串
\pset numericlocale [on|off] # 切换特定于区域设置的数字格式
\pset pager [on|off|always] # 控制分页器使用
\pset recordsep STRING # 设置记录分隔符
\pset recordsep0 [on|off] # 在记录之间使用空终止符
\pset tableattr STRING # 设置 HTML 表格属性
\pset title STRING # 设置查询标题
\pset tuples_only [on|off] # 切换仅元组模式
\copy QUERY TO FILENAME [FORMAT] # 客户端 COPY(需要较少权限)
\copy QUERY TO STDOUT # 复制到标准输出
\copy TABLE FROM FILENAME [FORMAT] # 从文件导入数据
\e or \edit # 在编辑器中编辑当前查询缓冲区
\e FILENAME # 在编辑器中编辑文件
\ef [FUNCNAME] # 编辑函数定义
\ev [VIEWNAME] # 编辑视图定义
\w FILENAME or \write FILENAME # 将当前查询缓冲区写入文件
\i FILENAME or \include FILENAME # 从文件执行 SQL 命令
\ir FILENAME or \include_relative FILE # 执行相对路径文件
\s [FILENAME] # 显示命令历史记录(或保存到文件)
\o FILENAME or \out FILENAME # 将所有输出发送到文件
\o # 将输出返回到终端
\echo TEXT # 打印文本(在脚本中很有用)
\errverbose # 以详细形式显示最后一个错误
\q or \quit # 退出 psql
\! COMMAND or \shell COMMAND # 执行 shell 命令
\cd DIRECTORY # 更改工作目录
\pwd # 打印当前工作目录
\set VARIABLE VALUE # 设置 psql 变量
\unset VARIABLE # 取消设置 psql 变量
\setenv VARNAME VALUE # 设置环境变量
\getenv VARNAME # 获取环境变量值
\prompt [TEXT] VARIABLE # 提示用户输入并设置变量
\begin or BEGIN # 开始事务
\commit or COMMIT # 提交事务
\rollback or ROLLBACK # 回滚事务
\savepoint NAME # 创建保存点
\release SAVEPOINT # 释放保存点
\rollback TO SAVEPOINT # 回滚到保存点
\d+ TABLENAME # 显示表及其扩展信息和存储信息
\dt *.* # 列出所有模式中的所有表
\dn * # 列出所有模式
\du # 列出所有用户/角色
\db # 列出表空间
\dx # 列出已安装的扩展
\h or \help # 列出可用的 SQL 命令
\h COMMAND or \help COMMAND # 显示特定 SQL 命令的帮助
\? # 显示 psql 帮助
\copyright # 显示 PostgreSQL 版权/许可证信息
\version or SELECT version() # 显示 PostgreSQL 版本
-h, --host=HOSTNAME # 服务器主机名(默认:localhost)
-p, --port=PORT # 服务器端口(默认:5432)
-U, --username=USERNAME # PostgreSQL 用户名(默认:$USER)
-d, --dbname=DBNAME # 要连接的数据库名
-w, --no-password # 从不提示输入密码
-W, --password # 强制密码提示
-A, --no-align # 不对齐的表输出模式
-c, --command=COMMAND # 运行单个命令并退出
-C, --copy-only # (已弃用,使用 \copy 代替)
-d, --dbname=DBNAME # 指定数据库
-E, --echo-hidden # 显示内部查询
-e, --echo-all # 在发送前显示每个命令
-b, --echo-errors # 显示失败的命令
-f, --file=FILENAME # 从文件执行命令
-F, --field-separator=CHAR # 为不对齐输出设置字段分隔符
-H, --html # HTML 表格输出模式
-l, --list # 列出可用数据库并退出
-L, --log-file=FILENAME # 将会话记录到文件
-n, --no-readline # 禁用 readline(行编辑)
-o, --output=FILENAME # 将结果写入文件
-P, --pset=VARIABLE=VALUE # 设置打印选项
-q, --quiet # 静默运行(无横幅,单行模式)
-R, --record-separator=CHAR # 为不对齐输出设置记录分隔符
-S, --single-step # 单步模式(确认每个命令)
-s, --single-transaction # 在单个事务中执行文件
-t, --tuples-only # 仅打印行(无页眉/页脚)
-T, --table-attr=STRING # 设置 HTML 表格标签属性
-v, --set=VARIABLE=VALUE # 设置 psql 变量
-V, --version # 显示版本并退出
-x, --expanded # 扩展的表输出模式
-X, --no-psqlrc # 不读取 ~/.psqlrc 启动文件
-1, --single-line # 行尾终止 SQL 命令
-a, --all # (已弃用)
-j, --job=NUM # (用于 pg_dump 的并行转储)
--help # 显示帮助信息
--version # 显示版本
--on-error-stop # 在第一个错误时停止
# 提示变量
psql -v PROMPT1='%/%R%# ' # 设置主提示符
psql -v PROMPT2='%R%# ' # 设置续行提示符
psql -v PROMPT3='>> ' # 设置输出模式提示符
# 提示符扩展代码:
# %n = 数据库用户名
# %m = 数据库服务器主机名(第一部分)
# %> = 数据库服务器完整主机名
# %p = 数据库服务器端口
# %d = 数据库名
# %/ = 当前模式
# %~ = 类似于 %/,但如果模式与用户名匹配则为 ~
# %# = 如果是超级用户则为 #,否则为 >
# %? = 最后一个查询结果状态
# %% = 字面量 %
# %[..%] = 不可见字符(用于终端控制序列)
# 在 psql 启动时自动加载
# 设置默认选项
\set QUIET ON
\set SQLHISTSIZE 10000
# 配置输出
\pset null '[NULL]'
\pset border 2
\pset linestyle unicode
\pset expanded auto
\pset pager always
# 定义有用的变量
\set conn_user 'SELECT current_user;'
\set dbsize 'SELECT pg_size_pretty(pg_database_size(current_database()));'
\set tables 'SELECT tablename FROM pg_tables WHERE schemaname = ''public'';'
\set functions 'SELECT proname FROM pg_proc;'
# 定义快捷方式
\set uptime 'SELECT now() - pg_postmaster_start_time() AS uptime;'
\set locks 'SELECT pid, usename, pg_blocking_pids(pid) as blocked_by, query, state FROM pg_stat_activity WHERE cardinality(pg_blocking_pids(pid)) > 0;'
# 设置计时
\timing ON
# 连接到默认数据库
\c mydb
-- 使用 :variable 语法
\set table_name mytable
SELECT * FROM :table_name;
-- 使用 :'variable' 表示字面量字符串
\set schema_name public
SELECT * FROM :"schema_name".mytable;
-- 在字符串上下文中使用 :'variable' 语法
\set username 'postgres'
SELECT * FROM pg_tables WHERE tableowner = :'username';
-- 使用 :' ' 进行标识符引用
\set id_name "customTable"
SELECT * FROM :"id_name";
-- 简单查询,立即执行
SELECT * FROM users;
-- 多行查询(直到分号结束)
SELECT id, name, email
FROM users
WHERE active = true;
-- 查询结果到文件
SELECT * FROM large_table \g output.txt
-- 查询结果通过管道传递给命令
SELECT * FROM users \g | wc -l
-- 执行上一个命令
\g
-- 仅作为元组执行(无页眉/页脚)
SELECT * FROM users;
-- 创建数据库
CREATE DATABASE myapp_db;
-- 创建模式
CREATE SCHEMA app_schema;
-- 创建表
CREATE TABLE app_schema.users (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 创建索引
CREATE INDEX idx_users_email ON app_schema.users(email);
-- 创建视图
CREATE VIEW app_schema.active_users AS
SELECT id, name, email FROM app_schema.users WHERE active = true;
-- 创建函数
CREATE OR REPLACE FUNCTION app_schema.get_user_count()
RETURNS INTEGER AS $$
BEGIN
RETURN (SELECT COUNT(*) FROM app_schema.users);
END;
$$ LANGUAGE plpgsql;
-- 插入单行
INSERT INTO users (name, email) VALUES ('John Doe', 'john@example.com');
-- 插入多行
INSERT INTO users (name, email) VALUES
('Jane Smith', 'jane@example.com'),
('Bob Johnson', 'bob@example.com');
-- 从查询插入
INSERT INTO users_backup SELECT * FROM users;
-- 更新数据
UPDATE users SET active = false WHERE last_login < now() - interval '30 days';
-- 删除数据
DELETE FROM users WHERE id = 999;
-- RETURNING 子句(查看更改内容)
UPDATE users SET status = 'active'
WHERE id = 1
RETURNING id, name, status;
-- 开始事务
BEGIN;
-- 或
START TRANSACTION;
-- 提交更改
COMMIT;
-- 或
END;
-- 回滚更改
ROLLBACK;
-- 创建保存点
SAVEPOINT sp1;
-- ... 执行语句 ...
ROLLBACK TO sp1; -- 回滚到保存点
RELEASE sp1; -- 释放保存点
-- 多语句事务
BEGIN;
INSERT INTO accounts (name, balance) VALUES ('Alice', 1000);
INSERT INTO accounts (name, balance) VALUES ('Bob', 1000);
UPDATE accounts SET balance = balance - 100 WHERE name = 'Alice';
UPDATE accounts SET balance = balance + 100 WHERE name = 'Bob';
COMMIT;
-- 设置事务隔离级别
BEGIN TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; -- PostgreSQL 默认
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- 显示当前事务状态
SHOW transaction_isolation;
-- 创建全文搜索向量
ALTER TABLE documents ADD COLUMN search_vector tsvector;
UPDATE documents SET search_vector =
to_tsvector('english', coalesce(title, '') || ' ' || coalesce(content, ''));
-- 为快速搜索创建索引
CREATE INDEX idx_documents_search ON documents USING GIN(search_vector);
-- 搜索文档
SELECT * FROM documents
WHERE search_vector @@ to_tsquery('english', 'database & tutorial');
-- 按相关性对结果排序
SELECT id, title, ts_rank(search_vector, query) AS rank
FROM documents, to_tsquery('english', 'database') AS query
WHERE search_vector @@ query
ORDER BY rank DESC;
-- 行号
SELECT id, name, salary,
ROW_NUMBER() OVER (ORDER BY salary DESC) AS rank
FROM employees;
-- 累计和
SELECT id, amount, date,
SUM(amount) OVER (ORDER BY date) AS running_total
FROM transactions;
-- 分区结果
SELECT id, department, salary,
ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS dept_rank
FROM employees;
-- LEAD/LAG(下一行/上一行)
SELECT id, date, amount,
LAG(amount) OVER (ORDER BY date) AS prev_amount,
LEAD(amount) OVER (ORDER BY date) AS next_amount
FROM transactions;
-- 存储 JSON
INSERT INTO documents VALUES (1, '{"name": "Alice", "age": 30}');
-- 访问 JSON 字段
SELECT data -> 'name' AS name FROM documents;
-- 使用默认值访问
SELECT data ->> 'name' AS name_text FROM documents; -- 返回文本
-- 检查键是否存在
SELECT * FROM documents WHERE data ? 'name';
-- JSON 数组操作
SELECT json_array_length(data) FROM documents;
-- JSON 聚合
SELECT json_agg(name) FROM users;
-- JSONB(二进制 JSON)在性能上更优
CREATE TABLE config (id INT, settings JSONB);
INSERT INTO config VALUES (1, '{"theme": "dark", "lang": "en"}');
-- JSONB 运算符效率更高
SELECT settings @> '{"theme": "dark"}' FROM config;
-- 简单 CTE
WITH active_users AS (
SELECT id, name, email FROM users WHERE active = true
)
SELECT * FROM active_users WHERE created_at > '2024-01-01';
-- 递归 CTE(树遍历)
WITH RECURSIVE category_hierarchy AS (
SELECT id, name, parent_id, 0 AS level
FROM categories
WHERE parent_id IS NULL
UNION ALL
SELECT c.id, c.name, c.parent_id, h.level + 1
FROM categories c
JOIN category_hierarchy h ON c.parent_id = h.id
)
SELECT * FROM category_hierarchy;
-- 多个 CTE
WITH orders_2024 AS (
SELECT * FROM orders WHERE EXTRACT(YEAR FROM order_date) = 2024
),
customer_totals AS (
SELECT customer_id, SUM(total_amount) AS total
FROM orders_2024
GROUP BY customer_id
)
SELECT c.name, ct.total
FROM customers c
JOIN customer_totals ct ON c.id = ct.customer_id
ORDER BY ct.total DESC;
# 执行文件
psql -d mydb -f script.sql
# 执行并将输出写入文件
psql -d mydb -f script.sql -o results.txt
# 执行并在出错时停止
psql -d mydb -f script.sql --on-error-stop
# 在单个事务中执行
psql -d mydb -f script.sql -s
# 多个文件(按顺序执行)
psql -d mydb -f init.sql -f seed.sql -f verify.sql
-- sample_script.sql
-- 设置执行模式
\set ON_ERROR_STOP ON
\set QUIET OFF
-- 如果需要,删除现有对象
DROP TABLE IF EXISTS temp_table;
-- 创建表
CREATE TABLE temp_table (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
-- 插入数据
INSERT INTO temp_table (name) VALUES
('Record 1'),
('Record 2'),
('Record 3');
-- 验证结果
SELECT * FROM temp_table;
-- 清理
DROP TABLE temp_table;
-- 报告
\echo 'Script completed successfully!'
#!/bin/bash
# 使用 psql 变量的 Bash 脚本
DATABASE="myapp_db"
TABLE_NAME="users"
SCHEMA_NAME="public"
# 使用变量替换执行
psql -d $DATABASE -v table_name=$TABLE_NAME \
-v schema_name=$SCHEMA_NAME -c "
SELECT COUNT(*) FROM :schema_name.:table_name;
"
# 遍历数据库
for db in $(psql -l | awk '{print $1}'); do
if [[ ! "$db" =~ "template" ]]; then
echo "Backing up $db..."
pg_dump $db > /backups/$db.sql
fi
done
-- 服务器端 COPY(文件操作需要超级用户权限)
COPY users (id, name, email)
TO '/tmp/users.csv'
WITH (FORMAT CSV, HEADER TRUE, QUOTE '"', ESCAPE '\\');
-- 导入 CSV
COPY users (id, name, email)
FROM '/tmp/users.csv'
WITH (FORMAT CSV, HEADER TRUE, QUOTE '"', ESCAPE '\\');
-- 制表符分隔值
COPY users TO '/tmp/users.tsv' WITH (FORMAT TEXT, DELIMITER E'\t');
-- 处理 NULL
COPY users TO '/tmp/users.csv'
WITH (FORMAT CSV, NULL 'N/A', QUOTE '"');
# 导出到 CSV(从 psql)
\copy users TO '/home/user/users.csv' WITH (FORMAT CSV, HEADER)
# 导出查询结果
\copy (SELECT id, name, email FROM users WHERE active = true) \
TO '/tmp/active_users.csv' WITH (FORMAT CSV, HEADER)
# 导入 CSV
\copy users (id, name, email) FROM '/tmp/users.csv' WITH (FORMAT CSV, HEADER)
# 导出到标准输出(管道到文件)
\copy users TO STDOUT WITH (FORMAT CSV, HEADER) > users.csv
# 从标准输入导入
cat users.csv | \copy users FROM STDIN WITH (FORMAT CSV, HEADER)
# 转储整个数据库
pg_dump -d mydb -U postgres > mydb_backup.sql
# 使用自定义格式转储(压缩)
pg_dump -d mydb -Fc > mydb_backup.dump
# 转储特定表
pg_dump -d mydb -t users > users_backup.sql
# 仅转储数据
pg_dump -d mydb -a > mydb_data.sql
# 仅转储模式
pg_dump -d mydb -s > mydb_schema.sql
# 从 SQL 文件恢复
psql -d mydb_restored -f mydb_backup.sql
# 从自定义格式恢复
pg_restore -d mydb_restored mydb_backup.dump
# 列出转储内容
pg_restore -l mydb_backup.dump
-- 显示查询执行计划
EXPLAIN SELECT * FROM users WHERE id = 1;
-- 带有实际执行的详细分析
EXPLAIN ANALYZE SELECT * FROM users WHERE id = 1;
-- 显示更多细节
EXPLAIN (ANALYZE, BUFFERS, VERBOSE)
SELECT * FROM users WHERE active = true;
-- JSON 输出,用于程序化解析
EXPLAIN (FORMAT JSON, ANALYZE)
SELECT COUNT(*) FROM users;
-- 当前查询
SELECT pid, usename, state, query FROM pg_stat_activity;
-- 长时间运行的查询
SELECT pid, usename, now() - query_start AS duration, query
FROM pg_stat_activity
WHERE state != 'idle'
ORDER BY query_start;
-- 阻塞查询
SELECT blocked_pid, blocking_pid, blocked_statement, blocking_statement
FROM pg_stat_statements;
-- 表大小
SELECT schemaname, tablename, pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS size
FROM pg_tables
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;
-- 数据库大小
SELECT pg_size_pretty(pg_database_size('mydb'));
# 启用查询计时
\timing ON
# 禁用查询计时
\timing OFF
# 在批处理模式下
psql -d mydb -c "\timing ON" -f script.sql
# 将所有查询记录到文件
psql -d mydb -L query.log -f script.sql
# 显示内部查询(系统查询)
psql -d mydb -E
-- 创建用户(角色)
CREATE USER appuser WITH PASSWORD 'secure_password';
-- 创建没有登录权限的角色
CREATE ROLE admin_role;
-- 修改用户
ALTER USER appuser WITH PASSWORD 'new_password';
-- 创建超级用户
CREATE USER superuser_name WITH PASSWORD 'password' SUPERUSER;
-- 列出用户
\du
-- 删除用户
DROP USER appuser;
-- 授予数据库使用权限
GRANT USAGE ON SCHEMA public TO appuser;
-- 授予表权限
GRANT SELECT, INSERT, UPDATE, DELETE ON users TO appuser;
-- 授予所有权限
GRANT ALL PRIVILEGES ON users TO appuser;
-- 授予序列权限(用于自增)
GRANT USAGE, SELECT ON SEQUENCE users_id_seq TO appuser;
-- 授予所有表权限
GRANT SELECT ON ALL TABLES IN SCHEMA public TO appuser;
-- 为未来的表设置默认权限
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO appuser;
-- 查看权限
\dp users
\dp+ users
-- 在表上启用 RLS
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
-- 创建策略
CREATE POLICY user_policy ON users
USING (id = current_user_id()); -- 这需要实现
-- 查看策略
\d+ users
# 详细显示最后一个错误
\errverbose
# 执行计时
\timing
# 回显发送到服务器的所有命令
\set ECHO all
# 列出所有变量
\set
# 查看特定变量
\echo :DBNAME
# 动态查询执行
\set query 'SELECT * FROM users WHERE id = ' :user_id
:query
# 设置自定义提示符
psql -v PROMPT1='user@db> '
psql -v PROMPT1='%/%R%# ' # database/role#
# 在 .psqlrc 中
\set PROMPT1 '%n@%m:%>/%/ %R%# '
\set PROMPT2 '> '
\set PROMPT3 '>> '
-- 列出函数
\df
-- 显示函数源代码
\df+ function_name
-- 创建函数
CREATE OR REPLACE FUNCTION get_user(user_id INT)
RETURNS TABLE(id INT, name TEXT, email TEXT) AS $$
BEGIN
RETURN QUERY
SELECT u.id, u.name, u.email FROM users u WHERE u.id = user_id;
END;
$$ LANGUAGE plpgsql;
-- 执行函数
SELECT * FROM get_user(1);
-- 存储过程(无返回值)
CREATE OR REPLACE PROCEDURE archive_old_records()
AS $$
BEGIN
INSERT INTO archived_users
SELECT * FROM users WHERE created_at < now() - interval '1 year';
DELETE FROM users WHERE created_at < now() - interval '1 year';
COMMIT;
END;
$$ LANGUAGE plpgsql;
-- 调用过程
CALL archive_old_records();
-- 创建触发器函数
CREATE OR REPLACE FUNCTION update_user_timestamp()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- 创建触发器
CREATE TRIGGER user_update_timestamp
BEFORE UPDATE ON users
FOR EACH ROW
EXECUTE FUNCTION update_user_timestamp();
-- 查看触发器
\d+ users
-- 删除触发器
DROP TRIGGER user_update_timestamp ON users;
# 完整数据库备份(自定义格式)
pg_dump -d production_db -Fc -j 4 > backup.dump
# 带压缩的备份
pg_dump -d production_db -Fc -Z 9 > backup.dump
# 并行备份(适用于大型数据库,速度
PostgreSQL psql (PostgreSQL interactive terminal) is the primary command-line client for interacting with PostgreSQL databases. It provides both interactive query execution and powerful scripting capabilities for database management and administration.
Use this skill when:
\dt, \d)psql [OPTIONS] [DBNAME [USERNAME]]
# Connect with username and host
psql -U username -h hostname -p 5432 -d database_name
# Connect using connection string
psql postgresql://username:password@hostname:5432/database_name
# Connect with password prompt
psql -U postgres -h localhost -W
# Connect to specific database on local machine
psql -d myapp_development
# Environment variables (alternative)
export PGUSER=postgres
export PGPASSWORD=mypassword
export PGHOST=localhost
export PGPORT=5432
export PGDATABASE=mydb
psql
Standard URI format :
postgresql://[user[:password]@][netloc][:port][/dbname][?param1=value1&...]
Example :
postgresql://app_user:secretpass@db.example.com:5432/production_db?sslmode=require
Password file (.pgpass) :
# ~/.pgpass (chmod 600)
hostname:port:database:username:password
localhost:5432:mydb:postgres:mypassword
*.example.com:5432:*:appuser:apppass
Connection via SSH tunnel :
ssh -L 5432:localhost:5432 user@remote-host
psql -U postgres -h localhost
# Require SSL
psql -h hostname -sslmode require -U username database
# Verify certificate
psql -h hostname -sslmode verify-full \
-sslcert=/path/to/client-cert.crt \
-sslkey=/path/to/client-key.key \
-sslrootcert=/path/to/ca-cert.crt database
# SSL modes: disable, allow, prefer (default), require, verify-ca, verify-full
\l or \list # List all databases
\l+ or \list+ # List databases with sizes
\c or \connect DATABASE USER # Connect to different database
\dn or \dn+ # List schemas (namespaces)
\dt or \dt+ # List tables in current schema
\di or \di+ # List indexes
\dv or \dv+ # List views
\dm or \dm+ # List materialized views
\ds or \ds+ # List sequences
\df or \df+ # List functions/procedures
\da or \da+ # List aggregates
\dT or \dT+ # List data types
\dF or \dF+ # List text search configurations
\d or \d NAME # Describe table, view, index, sequence, or function
\d+ or \d+ NAME # Extended description with details
\da PATTERN # List aggregate functions matching pattern
\db or \db+ # List tablespaces
\dc or \dc+ # List character set encodings
\dC or \dC+ # List type casts
\dd or \dd+ # List object descriptions/comments
\dD or \dD+ # List domains
\de or \de+ # List foreign data wrappers
\dE or \dE+ # List foreign servers
\dF or \dF+ # List text search configurations
\dFd or \dFd+ # List text search dictionaries
\dFp or \dFp+ # List text search parsers
\dFt or \dFt+ # List text search templates
\dg or \dg+ # List database roles/users
\dl or \dl+ # List large objects (same as \lo_list)
\dL or \dL+ # List procedural languages
\dO or \dO+ # List collations
\dp or \dp+ # List table access privileges
\dRp or \dRp+ # List replication origins
\dRs or \dRs+ # List replication subscriptions
\ds or \ds+ # List sequences
\dt or \dt+ # List tables
\dU or \dU+ # List user mapping
\du or \du+ # List roles
\dv or \dv+ # List views
\dx or \dx+ # List extensions
\dX or \dX+ # List extended statistics
\a # Toggle between aligned and unaligned output
\C [STRING] # Set table title
\f [STRING] # Set field separator for unaligned output
\H # Toggle HTML output mode
\pset OPTION [VALUE] # Set output option (detailed below)
\t [on|off] # Toggle tuple-only output (no headers/footers)
\T [STRING] # Set HTML table tag attributes
\x or \x [on|off|auto] # Toggle expanded/vertical output
\g or \g [FILENAME|COMMAND] # Execute query and send output to file/command
\pset border [0-2] # Set border display (0=none, 1=ascii, 2=unicode)
\pset columns WIDTH # Set column width limit
\pset csv # Set CSV output format
\pset expanded [on|off|auto] # Toggle expanded output
\pset fieldsep STRING # Set field separator
\pset footer [on|off] # Toggle footer display
\pset format [aligned|unaligned|csv|tsv|html|latex|latex-longtable|troff-ms]
\pset header [on|off] # Toggle header display
\pset linestyle [ascii|old-ascii|unicode] # Set line drawing style
\pset null STRING # Set string to represent NULL
\pset numericlocale [on|off] # Toggle locale-specific number formatting
\pset pager [on|off|always] # Control pager usage
\pset recordsep STRING # Set record separator
\pset recordsep0 [on|off] # Use null terminator between records
\pset tableattr STRING # Set HTML table attributes
\pset title STRING # Set query title
\pset tuples_only [on|off] # Toggle tuple-only mode
\copy QUERY TO FILENAME [FORMAT] # Client-side COPY (requires fewer permissions)
\copy QUERY TO STDOUT # Copy to standard output
\copy TABLE FROM FILENAME [FORMAT] # Import data from file
\e or \edit # Edit current query buffer in editor
\e FILENAME # Edit file in editor
\ef [FUNCNAME] # Edit function definition
\ev [VIEWNAME] # Edit view definition
\w FILENAME or \write FILENAME # Write current query buffer to file
\i FILENAME or \include FILENAME # Execute SQL commands from file
\ir FILENAME or \include_relative FILE # Execute relative path file
\s [FILENAME] # Show command history (or save to file)
\o FILENAME or \out FILENAME # Send all output to file
\o # Return output to terminal
\echo TEXT # Print text (useful in scripts)
\errverbose # Show last error in verbose form
\q or \quit # Quit psql
\! COMMAND or \shell COMMAND # Execute shell command
\cd DIRECTORY # Change working directory
\pwd # Print current working directory
\set VARIABLE VALUE # Set psql variable
\unset VARIABLE # Unset psql variable
\setenv VARNAME VALUE # Set environment variable
\getenv VARNAME # Get environment variable value
\prompt [TEXT] VARIABLE # Prompt user for input and set variable
\begin or BEGIN # Start transaction
\commit or COMMIT # Commit transaction
\rollback or ROLLBACK # Rollback transaction
\savepoint NAME # Create savepoint
\release SAVEPOINT # Release savepoint
\rollback TO SAVEPOINT # Rollback to savepoint
\d+ TABLENAME # Show table with extended info and storage info
\dt *.* # List all tables in all schemas
\dn * # List all schemas
\du # List all users/roles
\db # List tablespaces
\dx # List installed extensions
\h or \help # List available SQL commands
\h COMMAND or \help COMMAND # Show help for specific SQL command
\? # Show psql help
\copyright # Show PostgreSQL copyright/license info
\version or SELECT version() # Show PostgreSQL version
-h, --host=HOSTNAME # Server host name (default: localhost)
-p, --port=PORT # Server port (default: 5432)
-U, --username=USERNAME # PostgreSQL user name (default: $USER)
-d, --dbname=DBNAME # Database name to connect
-w, --no-password # Never prompt for password
-W, --password # Force password prompt
-A, --no-align # Unaligned table output mode
-c, --command=COMMAND # Run single command and exit
-C, --copy-only # (deprecated, use \copy instead)
-d, --dbname=DBNAME # Specify database
-E, --echo-hidden # Display internal queries
-e, --echo-all # Display each command before sending
-b, --echo-errors # Display failed commands
-f, --file=FILENAME # Execute commands from file
-F, --field-separator=CHAR # Set field separator for unaligned output
-H, --html # HTML table output mode
-l, --list # List available databases and exit
-L, --log-file=FILENAME # Log session to file
-n, --no-readline # Disable readline (line editing)
-o, --output=FILENAME # Write results to file
-P, --pset=VARIABLE=VALUE # Set printing option
-q, --quiet # Run quietly (no banner, single-line mode)
-R, --record-separator=CHAR # Set record separator for unaligned output
-S, --single-step # Single-step mode (confirm each command)
-s, --single-transaction # Execute file in single transaction
-t, --tuples-only # Print rows only (no headers/footers)
-T, --table-attr=STRING # Set HTML table tag attributes
-v, --set=VARIABLE=VALUE # Set psql variable
-V, --version # Show version and exit
-x, --expanded # Expanded table output mode
-X, --no-psqlrc # Do not read ~/.psqlrc startup file
-1, --single-line # End of line terminates SQL command
-a, --all # (deprecated)
-j, --job=NUM # (for parallel dumps with pg_dump)
--help # Show help message
--version # Show version
--on-error-stop # Stop on first error
# Prompt variables
psql -v PROMPT1='%/%R%# ' # Set primary prompt
psql -v PROMPT2='%R%# ' # Set continuation prompt
psql -v PROMPT3='>> ' # Set output mode prompt
# Prompt expansion codes:
# %n = Database user name
# %m = Database server hostname (first part)
# %> = Database server hostname full
# %p = Database server port
# %d = Database name
# %/ = Current schema
# %~ = Like %/ but ~ if schema matches user name
# %# = # if superuser, > otherwise
# %? = Last query result status
# %% = Literal %
# %[..%] = Invisible characters (for terminal control sequences)
# Auto-load on psql startup
# Set default options
\set QUIET ON
\set SQLHISTSIZE 10000
# Configure output
\pset null '[NULL]'
\pset border 2
\pset linestyle unicode
\pset expanded auto
\pset pager always
# Define useful variables
\set conn_user 'SELECT current_user;'
\set dbsize 'SELECT pg_size_pretty(pg_database_size(current_database()));'
\set tables 'SELECT tablename FROM pg_tables WHERE schemaname = ''public'';'
\set functions 'SELECT proname FROM pg_proc;'
# Define shortcuts
\set uptime 'SELECT now() - pg_postmaster_start_time() AS uptime;'
\set locks 'SELECT pid, usename, pg_blocking_pids(pid) as blocked_by, query, state FROM pg_stat_activity WHERE cardinality(pg_blocking_pids(pid)) > 0;'
# Set timing
\timing ON
# Connect to default database
\c mydb
-- Using :variable syntax
\set table_name mytable
SELECT * FROM :table_name;
-- Using :'variable' for literal strings
\set schema_name public
SELECT * FROM :"schema_name".mytable;
-- Using :'variable' syntax in string context
\set username 'postgres'
SELECT * FROM pg_tables WHERE tableowner = :'username';
-- Using :' ' for identifier quoting
\set id_name "customTable"
SELECT * FROM :"id_name";
-- Simple query with immediate execution
SELECT * FROM users;
-- Multi-line query (continues until semicolon)
SELECT id, name, email
FROM users
WHERE active = true;
-- Query with results to file
SELECT * FROM large_table \g output.txt
-- Query with pipe to command
SELECT * FROM users \g | wc -l
-- Execute previous command
\g
-- Execute as only tuples (no headers/footers)
SELECT * FROM users;
-- Create database
CREATE DATABASE myapp_db;
-- Create schema
CREATE SCHEMA app_schema;
-- Create table
CREATE TABLE app_schema.users (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Create index
CREATE INDEX idx_users_email ON app_schema.users(email);
-- Create view
CREATE VIEW app_schema.active_users AS
SELECT id, name, email FROM app_schema.users WHERE active = true;
-- Create function
CREATE OR REPLACE FUNCTION app_schema.get_user_count()
RETURNS INTEGER AS $$
BEGIN
RETURN (SELECT COUNT(*) FROM app_schema.users);
END;
$$ LANGUAGE plpgsql;
-- Insert single row
INSERT INTO users (name, email) VALUES ('John Doe', 'john@example.com');
-- Insert multiple rows
INSERT INTO users (name, email) VALUES
('Jane Smith', 'jane@example.com'),
('Bob Johnson', 'bob@example.com');
-- Insert from query
INSERT INTO users_backup SELECT * FROM users;
-- Update data
UPDATE users SET active = false WHERE last_login < now() - interval '30 days';
-- Delete data
DELETE FROM users WHERE id = 999;
-- RETURNING clause (see what was changed)
UPDATE users SET status = 'active'
WHERE id = 1
RETURNING id, name, status;
-- Begin transaction
BEGIN;
-- or
START TRANSACTION;
-- Commit changes
COMMIT;
-- or
END;
-- Rollback changes
ROLLBACK;
-- Create savepoint
SAVEPOINT sp1;
-- ... execute statements ...
ROLLBACK TO sp1; -- Rollback to savepoint
RELEASE sp1; -- Release savepoint
-- Multi-statement transaction
BEGIN;
INSERT INTO accounts (name, balance) VALUES ('Alice', 1000);
INSERT INTO accounts (name, balance) VALUES ('Bob', 1000);
UPDATE accounts SET balance = balance - 100 WHERE name = 'Alice';
UPDATE accounts SET balance = balance + 100 WHERE name = 'Bob';
COMMIT;
-- Set transaction isolation level
BEGIN TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; -- PostgreSQL default
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- Show current transaction status
SHOW transaction_isolation;
-- Create full-text search vector
ALTER TABLE documents ADD COLUMN search_vector tsvector;
UPDATE documents SET search_vector =
to_tsvector('english', coalesce(title, '') || ' ' || coalesce(content, ''));
-- Create index for fast search
CREATE INDEX idx_documents_search ON documents USING GIN(search_vector);
-- Search documents
SELECT * FROM documents
WHERE search_vector @@ to_tsquery('english', 'database & tutorial');
-- Ranking results by relevance
SELECT id, title, ts_rank(search_vector, query) AS rank
FROM documents, to_tsquery('english', 'database') AS query
WHERE search_vector @@ query
ORDER BY rank DESC;
-- Row number
SELECT id, name, salary,
ROW_NUMBER() OVER (ORDER BY salary DESC) AS rank
FROM employees;
-- Running sum
SELECT id, amount, date,
SUM(amount) OVER (ORDER BY date) AS running_total
FROM transactions;
-- Partition results
SELECT id, department, salary,
ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS dept_rank
FROM employees;
-- LEAD/LAG (next/previous row)
SELECT id, date, amount,
LAG(amount) OVER (ORDER BY date) AS prev_amount,
LEAD(amount) OVER (ORDER BY date) AS next_amount
FROM transactions;
-- Store JSON
INSERT INTO documents VALUES (1, '{"name": "Alice", "age": 30}');
-- Access JSON fields
SELECT data -> 'name' AS name FROM documents;
-- Access with default
SELECT data ->> 'name' AS name_text FROM documents; -- Returns text
-- Check if key exists
SELECT * FROM documents WHERE data ? 'name';
-- JSON array operations
SELECT json_array_length(data) FROM documents;
-- JSON aggregation
SELECT json_agg(name) FROM users;
-- JSONB (binary JSON) is preferred for performance
CREATE TABLE config (id INT, settings JSONB);
INSERT INTO config VALUES (1, '{"theme": "dark", "lang": "en"}');
-- JSONB operators are more efficient
SELECT settings @> '{"theme": "dark"}' FROM config;
-- Simple CTE
WITH active_users AS (
SELECT id, name, email FROM users WHERE active = true
)
SELECT * FROM active_users WHERE created_at > '2024-01-01';
-- Recursive CTE (tree traversal)
WITH RECURSIVE category_hierarchy AS (
SELECT id, name, parent_id, 0 AS level
FROM categories
WHERE parent_id IS NULL
UNION ALL
SELECT c.id, c.name, c.parent_id, h.level + 1
FROM categories c
JOIN category_hierarchy h ON c.parent_id = h.id
)
SELECT * FROM category_hierarchy;
-- Multiple CTEs
WITH orders_2024 AS (
SELECT * FROM orders WHERE EXTRACT(YEAR FROM order_date) = 2024
),
customer_totals AS (
SELECT customer_id, SUM(total_amount) AS total
FROM orders_2024
GROUP BY customer_id
)
SELECT c.name, ct.total
FROM customers c
JOIN customer_totals ct ON c.id = ct.customer_id
ORDER BY ct.total DESC;
# Execute file
psql -d mydb -f script.sql
# Execute with output to file
psql -d mydb -f script.sql -o results.txt
# Execute with error stopping
psql -d mydb -f script.sql --on-error-stop
# Execute in single transaction
psql -d mydb -f script.sql -s
# Multiple files (executed in order)
psql -d mydb -f init.sql -f seed.sql -f verify.sql
-- sample_script.sql
-- Set execution mode
\set ON_ERROR_STOP ON
\set QUIET OFF
-- Drop existing objects if needed
DROP TABLE IF EXISTS temp_table;
-- Create table
CREATE TABLE temp_table (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
-- Insert data
INSERT INTO temp_table (name) VALUES
('Record 1'),
('Record 2'),
('Record 3');
-- Verify results
SELECT * FROM temp_table;
-- Cleanup
DROP TABLE temp_table;
-- Report
\echo 'Script completed successfully!'
#!/bin/bash
# Bash script with psql variables
DATABASE="myapp_db"
TABLE_NAME="users"
SCHEMA_NAME="public"
# Execute with variable substitution
psql -d $DATABASE -v table_name=$TABLE_NAME \
-v schema_name=$SCHEMA_NAME -c "
SELECT COUNT(*) FROM :schema_name.:table_name;
"
# Loop through databases
for db in $(psql -l | awk '{print $1}'); do
if [[ ! "$db" =~ "template" ]]; then
echo "Backing up $db..."
pg_dump $db > /backups/$db.sql
fi
done
-- Server-side COPY (requires superuser for file operations)
COPY users (id, name, email)
TO '/tmp/users.csv'
WITH (FORMAT CSV, HEADER TRUE, QUOTE '"', ESCAPE '\\');
-- Import CSV
COPY users (id, name, email)
FROM '/tmp/users.csv'
WITH (FORMAT CSV, HEADER TRUE, QUOTE '"', ESCAPE '\\');
-- Tab-separated values
COPY users TO '/tmp/users.tsv' WITH (FORMAT TEXT, DELIMITER E'\t');
-- With NULL handling
COPY users TO '/tmp/users.csv'
WITH (FORMAT CSV, NULL 'N/A', QUOTE '"');
# Export to CSV (from psql)
\copy users TO '/home/user/users.csv' WITH (FORMAT CSV, HEADER)
# Export with query results
\copy (SELECT id, name, email FROM users WHERE active = true) \
TO '/tmp/active_users.csv' WITH (FORMAT CSV, HEADER)
# Import CSV
\copy users (id, name, email) FROM '/tmp/users.csv' WITH (FORMAT CSV, HEADER)
# Export to stdout (pipe to file)
\copy users TO STDOUT WITH (FORMAT CSV, HEADER) > users.csv
# Import from stdin
cat users.csv | \copy users FROM STDIN WITH (FORMAT CSV, HEADER)
# Dump entire database
pg_dump -d mydb -U postgres > mydb_backup.sql
# Dump with custom format (compressed)
pg_dump -d mydb -Fc > mydb_backup.dump
# Dump specific table
pg_dump -d mydb -t users > users_backup.sql
# Dump with data only
pg_dump -d mydb -a > mydb_data.sql
# Dump schema only
pg_dump -d mydb -s > mydb_schema.sql
# Restore from SQL file
psql -d mydb_restored -f mydb_backup.sql
# Restore from custom format
pg_restore -d mydb_restored mydb_backup.dump
# List contents of dump
pg_restore -l mydb_backup.dump
-- Show query execution plan
EXPLAIN SELECT * FROM users WHERE id = 1;
-- Detailed analysis with actual execution
EXPLAIN ANALYZE SELECT * FROM users WHERE id = 1;
-- Show more details
EXPLAIN (ANALYZE, BUFFERS, VERBOSE)
SELECT * FROM users WHERE active = true;
-- JSON output for programmatic parsing
EXPLAIN (FORMAT JSON, ANALYZE)
SELECT COUNT(*) FROM users;
-- Current queries
SELECT pid, usename, state, query FROM pg_stat_activity;
-- Long-running queries
SELECT pid, usename, now() - query_start AS duration, query
FROM pg_stat_activity
WHERE state != 'idle'
ORDER BY query_start;
-- Blocking queries
SELECT blocked_pid, blocking_pid, blocked_statement, blocking_statement
FROM pg_stat_statements;
-- Table sizes
SELECT schemaname, tablename, pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS size
FROM pg_tables
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;
-- Database size
SELECT pg_size_pretty(pg_database_size('mydb'));
# Enable query timing
\timing ON
# Disable query timing
\timing OFF
# In batch mode
psql -d mydb -c "\timing ON" -f script.sql
# Log all queries to file
psql -d mydb -L query.log -f script.sql
# Show internal queries (system queries)
psql -d mydb -E
-- Create user (role)
CREATE USER appuser WITH PASSWORD 'secure_password';
-- Create role without login privilege
CREATE ROLE admin_role;
-- Alter user
ALTER USER appuser WITH PASSWORD 'new_password';
-- Create superuser
CREATE USER superuser_name WITH PASSWORD 'password' SUPERUSER;
-- List users
\du
-- Drop user
DROP USER appuser;
-- Grant database usage
GRANT USAGE ON SCHEMA public TO appuser;
-- Grant table permissions
GRANT SELECT, INSERT, UPDATE, DELETE ON users TO appuser;
-- Grant all permissions
GRANT ALL PRIVILEGES ON users TO appuser;
-- Grant sequence permissions (for auto-increment)
GRANT USAGE, SELECT ON SEQUENCE users_id_seq TO appuser;
-- Grant to all tables
GRANT SELECT ON ALL TABLES IN SCHEMA public TO appuser;
-- Make privileges default for future tables
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO appuser;
-- View permissions
\dp users
\dp+ users
-- Enable RLS on table
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
-- Create policy
CREATE POLICY user_policy ON users
USING (id = current_user_id()); -- This would need to be implemented
-- View policies
\d+ users
# Show last error in detail
\errverbose
# Execution timing
\timing
# Echo all commands sent to server
\set ECHO all
# List all variables
\set
# View specific variable
\echo :DBNAME
# Dynamic query execution
\set query 'SELECT * FROM users WHERE id = ' :user_id
:query
# Set custom prompts
psql -v PROMPT1='user@db> '
psql -v PROMPT1='%/%R%# ' # database/role#
# In .psqlrc
\set PROMPT1 '%n@%m:%>/%/ %R%# '
\set PROMPT2 '> '
\set PROMPT3 '>> '
-- List functions
\df
-- Show function source
\df+ function_name
-- Create function
CREATE OR REPLACE FUNCTION get_user(user_id INT)
RETURNS TABLE(id INT, name TEXT, email TEXT) AS $$
BEGIN
RETURN QUERY
SELECT u.id, u.name, u.email FROM users u WHERE u.id = user_id;
END;
$$ LANGUAGE plpgsql;
-- Execute function
SELECT * FROM get_user(1);
-- Stored procedure (no return value)
CREATE OR REPLACE PROCEDURE archive_old_records()
AS $$
BEGIN
INSERT INTO archived_users
SELECT * FROM users WHERE created_at < now() - interval '1 year';
DELETE FROM users WHERE created_at < now() - interval '1 year';
COMMIT;
END;
$$ LANGUAGE plpgsql;
-- Call procedure
CALL archive_old_records();
-- Create trigger function
CREATE OR REPLACE FUNCTION update_user_timestamp()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Create trigger
CREATE TRIGGER user_update_timestamp
BEFORE UPDATE ON users
FOR EACH ROW
EXECUTE FUNCTION update_user_timestamp();
-- View triggers
\d+ users
-- Drop trigger
DROP TRIGGER user_update_timestamp ON users;
# Full database backup (custom format)
pg_dump -d production_db -Fc -j 4 > backup.dump
# Backup with compression
pg_dump -d production_db -Fc -Z 9 > backup.dump
# Parallel backup (faster for large databases)
pg_dump -d production_db -Fd -j 4 -f backup_dir
# Backup specific schemas
pg_dump -d production_db -n public -n app > schemas.sql
# Backup with custom format (allows selective restore)
pg_dump -d production_db -Fc > backup.dump
# View backup contents
pg_restore -l backup.dump | less
# Restore specific table
pg_restore -d restored_db -t users backup.dump
# List available backups
pg_dump -U postgres -l -w postgres
# Full backup
pg_dump -d mydb > base_backup.sql
# Enable WAL archiving (in postgresql.conf)
wal_level = replica
archive_mode = on
archive_command = 'cp %p /archive/%f'
# Restore to point in time
pg_restore -d recovered_db base_backup.sql
# Then apply WAL files up to target time
#!/bin/bash
# Simple connection pool using psql
MAX_CONNECTIONS=10
CONNECTION_POOL=()
for i in {1..$MAX_CONNECTIONS}; do
(
while true; do
psql -d mydb -c "SELECT 1"
sleep 60
done
) &
CONNECTION_POOL+=($!)
done
# Keep script running
wait
-- health_check.sql
SELECT
'PostgreSQL Version' AS check_type,
version() AS result
UNION ALL
SELECT
'Database Size',
pg_size_pretty(pg_database_size(current_database()))
UNION ALL
SELECT
'Active Connections',
count(*)::text
FROM pg_stat_activity
UNION ALL
SELECT
'Cache Hit Ratio',
ROUND(sum(heap_blks_hit)::numeric / (sum(heap_blks_hit) + sum(heap_blks_read)), 4)::text
FROM pg_statio_user_tables;
#!/bin/bash
# Weekly maintenance script
DATABASES=$(psql -t -c "SELECT datname FROM pg_database WHERE datistemplate = false AND datname != 'postgres';")
for db in $DATABASES; do
echo "Analyzing $db..."
psql -d "$db" -c "ANALYZE;"
echo "Vacuuming $db..."
psql -d "$db" -c "VACUUM;"
echo "Reindexing $db..."
psql -d "$db" -c "REINDEX DATABASE \"$db\";"
done
# Connect and execute in one line
psql -d mydb -c "SELECT COUNT(*) FROM users;"
# Execute file and exit
psql -d mydb -f script.sql
# Quiet mode (minimal output)
psql -q -d mydb -c "SELECT * FROM users LIMIT 1;"
# Pipe output to other commands
psql -d mydb -t -c "SELECT name FROM users;" | sort | uniq
# Verify connection without executing commands
psql -d mydb -c ""
# Add to ~/.psqlrc for convenient shortcuts
\set dbsize 'SELECT pg_size_pretty(pg_database_size(current_database()))'
\set uptime 'SELECT now() - pg_postmaster_start_time() AS uptime'
\set psql_version 'SELECT version()'
\set table_sizes 'SELECT schemaname, tablename, pg_size_pretty(pg_total_relation_size(schemaname||'\''.\'\'||tablename)) FROM pg_tables ORDER BY pg_total_relation_size(schemaname||'\''.\'\'||tablename) DESC'
# Usage in psql:
# :dbsize
# :table_sizes
# Set pager for large results
\pset pager always
# Use LIMIT for testing
SELECT * FROM huge_table LIMIT 10;
# Use OFFSET for pagination
SELECT * FROM users LIMIT 10 OFFSET 0;
SELECT * FROM users LIMIT 10 OFFSET 10;
# Fetch into file instead of terminal
\copy (SELECT * FROM huge_table) TO huge_export.csv;
# Verbose connection diagnostics
psql -d mydb -v verbose=on --echo-queries
# Check connection settings
psql --version
psql -d postgres -c "SHOW password_encryption;"
# TCP/IP connectivity test
psql -h hostname -d postgres -U postgres -c "SELECT 1;"
FATAL: password authentication failed
→ Check password, user exists, .pgpass has correct permissions (600)
FATAL: no pg_hba.conf entry for host
→ Database server's pg_hba.conf needs connection rule
FATAL: database "name" does not exist
→ Create database or check database name spelling
ERROR: permission denied for schema
→ Grant USAGE on schema to user
ERROR: syntax error
→ Check SQL syntax, use \h for help on commands
-- Find slow queries
SELECT * FROM pg_stat_statements
ORDER BY total_time DESC
LIMIT 10;
-- Check for missing indexes
SELECT schemaname, tablename, attname
FROM pg_stat_user_tables, pg_attribute
WHERE pg_stat_user_tables.relid = pg_attribute.attrelid
AND seq_scan > 0;
-- Check cache efficiency
SELECT
sum(heap_blks_read) as heap_read,
sum(heap_blks_hit) as heap_hit,
sum(heap_blks_hit) / (sum(heap_blks_hit) + sum(heap_blks_read)) AS ratio
FROM pg_statio_user_tables;
# In ~/.psqlrc
\set HISTSIZE 10000
\pset pager always
\pset null '[NULL]'
\pset linestyle unicode
# Environment variables for defaults
export PGHOST=localhost
export PGPORT=5432
export PGUSER=postgres
export PGDATABASE=mydb
export PGPASSFILE=$HOME/.pgpass
-- Aligned (default)
\pset format aligned
-- CSV
\pset format csv
\copy (SELECT * FROM users) TO STDOUT WITH (FORMAT CSV);
-- HTML
\pset format html
SELECT * FROM users LIMIT 5;
-- LaTeX
\pset format latex
SELECT * FROM users LIMIT 5;
-- Expanded (vertical)
\x
SELECT * FROM users LIMIT 1;
psql is a powerful, flexible command-line tool for PostgreSQL database administration and development. Key strengths:
Master psql to unlock efficient PostgreSQL workflows, from simple queries to complex database administration tasks.
Weekly Installs
129
Repository
GitHub Stars
35
First Seen
Jan 23, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykFail
Installed on
opencode117
codex117
gemini-cli114
github-copilot109
kimi-cli101
cursor101
Azure 升级评估与自动化工具 - 轻松迁移 Functions 计划、托管层级和 SKU
96,200 周安装
Prisma ORM 专家:模式设计、迁移、查询优化与关系建模全指南
3,000 周安装
Tauri v2 开发技能:使用 Web 前端和 Rust 构建跨平台桌面/移动应用
3,000 周安装
天气查询技能:无需API密钥获取实时天气和预报,支持全球城市和命令行调用
3,000 周安装
Sandbox Agent - AI 编码代理沙盒环境编排工具,支持多语言 SDK 和云服务集成
3,000 周安装
opencli:将网站转为命令行工具,复用Chrome登录状态,无需凭证 | 自动化爬虫替代方案
3,100 周安装
Govilo To Go:一键生成付费文件解锁链接,支持加密货币收款
3,000 周安装