You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何根据PostgreSQL插入语句返回结果决定事务提交或回滚

PostgreSQL中直接获取INSERT执行结果控制事务的方案

你在psql中看到的INSERT 0 1、INSERT 0 0返回值里,第二个数字就是当前语句实际插入/更新的行数,全程不需要执行额外SELECT查询,直接通过数据库内置能力就能拿到这个值,用来判断事务是提交还是回滚,常用实现分三类场景:

数据库端PL/pgSQL逻辑实现

如果事务逻辑直接在数据库侧通过匿名块、存储过程执行,用GET DIAGNOSTICS语法直接读取行统计值即可,无额外性能开销:

-- 测试表结构和你给出的一致
create table a(id int PRIMARY KEY, foo text, bar text);

DO $$
DECLARE
  v_affected_rows integer;
BEGIN
  -- 执行第一条UPSERT
  insert into a values(1, 'foo', 'bar') 
  on conflict (id) DO UPDATE SET foo = excluded.foo where a.bar = 'bar';
  -- 直接读取当前语句影响的行数
  GET DIAGNOSTICS v_affected_rows = ROW_COUNT;

  -- 无生效行直接回滚退出
  IF v_affected_rows = 0 THEN
    ROLLBACK;
    RETURN;
  END IF;

  -- 执行第二条UPSERT
  insert into a values(1, 'foo', 'bar') 
  on conflict (id) DO UPDATE SET foo = excluded.foo where a.bar = 'bara';
  GET DIAGNOSTICS v_affected_rows = ROW_COUNT;

  IF v_affected_rows = 0 THEN
    ROLLBACK;
    RETURN;
  END IF;

  -- 所有校验通过后提交事务
  COMMIT;
END $$;

这里拿到的v_affected_rows和psql客户端打印的返回值完全一致,统计逻辑是数据库执行语句时顺带完成的,没有额外IO开销。

应用层代码实现

如果逻辑是在业务应用代码中执行,所有主流PostgreSQL驱动都原生支持读取语句影响行数,不需要额外查询:

  • Java JDBC:executeUpdate()方法的返回值就是影响行数
  • Python psycopg2/psycopg3:游标执行完语句后,直接读取cursor.rowcount属性即可
  • Go pgx驱动:Exec方法返回的结果对象调用RowsAffected()就能拿到对应数值

以Python为例的实现代码:

import psycopg2

conn = psycopg2.connect("dbname=foouser")
cur = conn.cursor()
try:
    cur.execute("""
        insert into a values(1, 'foo', 'bar')
        on conflict (id) DO UPDATE SET foo = excluded.foo where a.bar = %s
    """, ("bara",))
    # 直接读取影响行数,无额外查询
    affected = cur.rowcount
    if affected == 0:
        conn.rollback()
    else:
        # 执行后续业务逻辑
        conn.commit()
except Exception:
    conn.rollback()
finally:
    cur.close()
    conn.close()

psql脚本场景实现

如果是直接在psql客户端写脚本执行,可以用psql内置的ROW_COUNT变量做条件判断:

START TRANSACTION;
insert into a values(1, 'foo', 'bar') on conflict (id) DO UPDATE SET foo = excluded.foo where a.bar = 'bara';
-- 判断上一条语句的影响行数
\if :ROW_COUNT = 0
  \echo 无行被插入/更新,执行回滚
  ROLLBACK;
\else
  \echo 执行正常,提交事务
  COMMIT;
\endif

内容的提问来源于stack exchange,提问作者irregular

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 19:57:11