跳到主要内容

PostgreSQL INSERT 实用教程(常用语法 + 事务安全 + 易错点)

INSERT 基本语法​

INSERT INTO 表名 (列1, 列2, ...)
VALUES (值1, 值2, ...);
-- 单行插入
INSERT INTO users (id, name, age, status) VALUES (1, 'Alice', 28, 1);
-- 插入时忽略列名:按表定义顺序插入
INSERT INTO users VALUES (2, 'Bob', 30, 1, '2025-01-01 10:00:00');
注意

不推荐“按默认顺序写 VALUES”,因为表结构调整后会导致插入错误,难以维护。

多行插入​

-- 一条语句插入多行
INSERT INTO users (name, age, status) VALUES ('Tom', 18, 1), ('Jerry', 24, 0), ('Lucy', 31, 1);

多行插入比循环插入更高效,适合批量录入。

信息

事务中一次插入多行能减少提交次数,适合大批量导入;但过大的单次事务可能导致锁等待和日志膨胀。

插入默认值与 NULL​

-- 使用列默认值
INSERT INTO users (name, status) VALUES ('Kate', DEFAULT);
-- 显式插入 NULL
INSERT INTO users (name, phone) VALUES ('David', NULL);
-- 省略某列:如果该列允许 NULL / 有默认值,可自动填充
INSERT INTO users (name) VALUES ('Emma');
注意

不能把字符串 'NULL' 当作 NULL 值来插入;如果列定义了 NOT NULL、CHECK、外键或唯一约束,值必须满足要求。

INSERT ... SELECT:从其他表导入​

-- 从另一个表复制数据
INSERT INTO users_archive (id, name, age) SELECT id, name, age FROM users WHERE status = 0;
-- 只插入部分列,做字段映射
INSERT INTO member_log (member_id, created_at, action) SELECT id, create_time, 'login' FROM users WHERE last_login_time IS NOT NULL;
信息

INSERT ... SELECT 非常适合做归档、同步和数据清洗。执行前通常先用 SELECT 验证目标结果行数和字段值。

RETURNING:直接拿到插入结果​

-- 插入后返回主键和字段值
INSERT INTO users (name, age, status) VALUES ('Nancy', 27, 1) RETURNING id, name, status;

在 PostgreSQL 中,RETURNING 非常实用,可直接用于应用层生成新记录的 ID 或状态。

注意

如果插入失败,RETURNING 不会返回任何结果;错误原因应从数据库报错中读取。

ON CONFLICT:有则更新,无则插入(UPSERT)​

适合“存在则更新,不存在则插入”的业务场景。

-- 假设 user_id 有唯一索引
INSERT INTO user_profile (user_id, nickname, updated_at) VALUES (1001, 'Tommy', NOW()) ON CONFLICT (user_id) DO UPDATE SET nickname = EXCLUDED.nickname, updated_at = NOW();
注意

关键条件:必须有唯一约束/唯一索引对应目标列,否则 ON CONFLICT 无法生效。没有唯一约束时,插入重复数据仍可能失败。

如果要忽略冲突而不报错,可使用:

INSERT INTO user_profile (user_id, nickname) VALUES (1001, 'Tommy') ON CONFLICT (user_id) DO NOTHING;

INSERT 与事务​

BEGIN;
INSERT INTO users (name, age, status) VALUES ('Zoe', 29, 1);
INSERT INTO user_log (user_id, action) VALUES (currval('users_id_seq'), 'created');
COMMIT;
信息

一组相关插入最好放在一个事务中:要么全部成功,要么全部回滚。否则插入用户但日志没写入会产生脏数据。

注意

如果事务中间有异常,通常需要执行 ROLLBACK,不能继续假定前面插入成功。

常见错误与最佳实践​

问题说明建议
列名写错会直接报错,插入失败优先明确列列表,减少歧义
唯一约束冲突重复主键/唯一索引导致失败使用 ON CONFLICT 或先检查
NULL / 默认值混淆NULL 与未赋值不是同一回事按列定义的允许性选择
批量插入过大事务日志和锁资源压力增大分批执行、控制每批大小

总结:INSERT 高频易错清单​

  • 1. 优先写出列名,避免依赖表结构顺序。
  • 2. 多行插入比循环单行更高效,适合批量录入。
  • 3. 使用 INSERT ... SELECT 处理数据归档和同步。
  • 4. RETURNING 能直接拿到插入后的 ID / 值。
  • 5. 唯一冲突时优先考虑 ON CONFLICT。
  • 6. 事务中相关插入要一起提交或回滚,避免半成功状态。
  • 7. 大批量插入要分批,避免锁和日志压力过大。