# 25P01 — 没有活动 SQL 事务（no_active_sql_transaction）

> PostgreSQL SQLSTATE 25P01：SAVEPOINT 等操作要求显式事务块的诊断与修复。
---

# 25P01 — 没有活动 SQL 事务（no_active_sql_transaction）

## 速览 {#at-a-glance}

`25P01` 表示操作需要活动 SQL 事务。选定案例在自动提交会话中发送 `SAVEPOINT`，得到精确错误且会话保持 `IDLE`；随后在 `BEGIN` 内重新执行并提交。

<!-- BEGIN SQLSTATE FACTS: generated by scripts/generate.py; do not edit -->

| 字段 | 值 |
| --- | --- |
| SQLSTATE | `25P01` |
| 条件名 | `no_active_sql_transaction` |
| 状态 | `有效` |
| 已知存在于 | `7.4` |
| 锁定快照 | `9.0.23, 9.1.24, 9.2.24, 9.3.25, 9.4.26, 9.5.25, 9.6.24, 10.23, 11.22, 12.22, 13.23, 14.24, 15.19, 16.15, 17.11, 18.6, 19beta3` |
| 宏 | `ERRCODE_NO_ACTIVE_SQL_TRANSACTION` |
| 别名 | `—` |

<!-- source facts: data/errcodes/25P01.json -->
<!-- END SQLSTATE FACTS -->

## 含义 {#meaning}

源码把语句名填入 `%s can only be used in transaction blocks`；本文的 `SAVEPOINT` 路径严重级别为 `ERROR`。同一 SQLSTATE 还覆盖 `COMMIT AND CHAIN`/`ROLLBACK AND CHAIN` 的错误，以及无事务时 `COMMIT`/`ROLLBACK` 的警告，固定报文是 `there is no transaction in progress`。

## 诊断 {#diagnosis}

执行 SAVEPOINT、RELEASE SAVEPOINT 或 ROLLBACK TO SAVEPOINT 前，先确认客户端已进入显式事务块。选定运行中失败的自动提交语句后仍为 `IDLE`；修复序列是 `BEGIN`、`SAVEPOINT`、`RELEASE`、`COMMIT`。

## 处理 {#response}

创建保存点前先启动显式事务。若操作误发在事务块外，应修正客户端事务包装后重试；本自动提交错误没有遗留失败事务块，因此不需要回滚。

## 源码报文 {#messages}

`xact.c` 用 `%s can only be used in transaction blocks` 组装语句级报文；本案例把 `%s` 替换为 `SAVEPOINT`，严重级别为 `ERROR`。`COMMIT AND CHAIN` 与 `ROLLBACK AND CHAIN` 在无事务块时使用同一动态形式；无事务时的 `COMMIT`/`ROLLBACK` 则使用 `WARNING` 报文 `there is no transaction in progress`。

## 实测诊断 {#observed}

`18.6 (Homebrew) / latest`：SQLSTATE `25P01`；主报文 `SAVEPOINT can only be used in transaction blocks`；错误后状态 `IDLE`；显式事务修复 `INTRANS → IDLE`。
`10.21 (Debian 10.21-1.pgdg90+1) / pg10`：SQLSTATE `25P01`；主报文 `SAVEPOINT can only be used in transaction blocks`；错误后状态 `IDLE`；显式事务修复 `INTRANS → IDLE`。

## 代表案例 {#case}

运行器从共享语句清单（registry）读取下列无事务保存点和显式块修复语句；完整断言、环境和清理见 [案例导出](../../data/cases/25p01.json)。

<!-- BEGIN SQLSTATE SNIPPET: no_active_sql_transaction -->
```sql
-- trigger
SAVEPOINT outside_block;
-- begin
BEGIN;
-- savepoint
SAVEPOINT inside_block;
-- release
RELEASE SAVEPOINT inside_block;
-- commit
COMMIT;
-- verify
SELECT 1;
```
<!-- END SQLSTATE SNIPPET -->

上述片段的 SQLSTATE、诊断、状态和修复断言来自共享语句清单（registry）（SHA-256 `a1ffffc778f82789f1c1ac4027a109fc76e4b315ef2e3a5bdbfc47c8f84ce951`）；[结构化证据](../../data/evidence/25p01.json)。

作者证据 ID：`identity`, `savepoint-path`, `runtime`。选定运行记录：`runtime.25P01-batch2-latest-20260909.latest`, `runtime.25P01-batch2-pg10-20260909.pg10`。
## 版本与边界 {#versions}

SAVEPOINT 案例在 18.6 与 10.21 返回相同主报文的 25P01，显式事务块修复后两个目标均回到 `IDLE`。

## 相关 {#related}

[25005 分支事务没有活动 SQL 事务](../25005/)、[25P02 失败 SQL 事务](../25p02/)、[25006 只读 SQL 事务](../25006/)。

## 来源 {#sources}

- [`src.errcodes.18.6`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/errcodes.txt) (SHA-256 `6e8de346643ba84aa3c9c6a73360acfc7b2dfb89162c06c08ce9bf5bcd5bbcba`)
- `src.calls.REL_18_6` — `raw/calls/REL_18_6.jsonl` (SHA-256 `9ee8a0e81d8f0825c5c1ae45583439859a26e602bdd4ce2f2a62aa278867ccbf`)
- [`src.xact.18.6`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/access/transam/xact.c#L3724-L3749) (SHA-256 `75b012c0b047d1dc905a30975c244beec366e45eac0dbf109fd21bcd611a8e39`)
- [`doc.savepoint.18.6`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/doc/src/sgml/ref/savepoint.sgml#L68-L78) (SHA-256 `aa6e167d373da6118249c87404a7b2ff8be8c7df790449814f1d9dc433bbd428`) · [official documentation](https://www.postgresql.org/docs/18/sql-savepoint.html)
- [`src.xact.savepoint.18.6`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/access/transam/xact.c#L4418-L4424) (SHA-256 `75b012c0b047d1dc905a30975c244beec366e45eac0dbf109fd21bcd611a8e39`)
