P0001 — raise_exception(引发异常)
RAISE EXCEPTION 未指定条件名或代码时的默认码。
英文手册覆盖始于 PostgreSQL 8.1. 来源历史与运行验证各自保留独立版本边界。
当前阅读 PG 18·选择有来源记录的版本
- aliases
- 未知
- class name
- PL/pgSQL Error
- condition name
- raise_exception
- lang
- en
- sqlstate
- P0001
版本定义 PG 18
速览 {#at-a-glance}
P0001 是 PostgreSQL 专用类别 P0(PL/pgSQL Error)中的 raise_exception 条件。不写条件名、也不写显式 SQLSTATE 的 RAISE EXCEPTION 会默认使用这个代码。报文由函数作者提供,因此 P0001 通常是应用或过程的控制信号,而不是某个服务器子系统的诊断。
严重级别和代码是两个选择。EXCEPTION 是 RAISE 的默认级别,通常会中止当前事务。NOTICE、WARNING、INFO、LOG 和 DEBUG 只按对应优先级生成消息;显式的 ERRCODE 也可以选择其他 SQLSTATE。读取时应始终同时记录严重级别和 SQLSTATE。
代表性案例 plpgsql_raise_exception 创建包含 RAISE EXCEPTION 'calibration exception' 的函数,调用它,再在同一自动提交连接上执行 SELECT 1。PostgreSQL 18.6 和 10.21 都返回 P0001、保留该报文,连接状态为 IDLE,并接受后续查询。下面的 SQL 摘录是共享注册表中的完整有序函数、调用和后续语句;实际运行中的模式限定函数名和清理由测试执行器统一管理。
含义与触发路径 {#meaning}
18.6 目录把 P0001 放在 PostgreSQL 专用的 P0 类 PL/pgSQL Error 中,并命名为 raise_exception。在 PL/pgSQL 执行器中,只有在未提供代码且级别不低于 ERROR 时才设置默认代码;之后执行器会报告调用方的报文,并附带可选的详细信息、提示和对象字段。
语法支持几条不同路径:
RAISE EXCEPTION 'message'默认使用P0001。RAISE EXCEPTION condition_name使用该条件自己的 SQLSTATE,因此不一定是P0001。RAISE EXCEPTION SQLSTATE '5-character-code'或RAISE ... USING ERRCODE = ...可以让过程暴露特定领域契约。除00000外,PostgreSQL 允许使用自选的五字符代码。- 较低级别的
RAISE WARNING 'message'只按该优先级送出消息。即使调用方显式选择了错误码,它也不是RAISE EXCEPTION的同一种事务事件。
无参数的 RAISE; 是活动异常处理器中的重新抛出控制。它的行为和 SQLSTATE 由正在重新抛出的异常决定,不是一次新的默认 P0001 事件。
报文与诊断 {#messages}
代表性注册表操作如下:
CREATE FUNCTION raise_exception_case() RETURNS void
LANGUAGE plpgsql AS $$
BEGIN
RAISE EXCEPTION 'calibration exception';
END
$$;
SELECT raise_exception_case();
SELECT 1;
实际运行的函数名由测试执行器生成并带模式限定。18.6 观察到的诊断是:
SQLSTATE: P0001
severity: ERROR
message_primary: calibration exception
context: PL/pgSQL function ...raise_exception_case() line 3 at RAISE
source: pl_exec.c / exec_stmt_raise / line 3923
P0001 没有统一的英文主报文,具体内容由函数提供。USING MESSAGE、DETAIL、HINT、COLUMN、CONSTRAINT、DATATYPE、TABLE 和 SCHEMA 可以添加结构化诊断。消息文本可以本地化而 SQLSTATE 保持不变,因此应按 P0001 分支,再读取结构化字段,不要解析主报文字符串。
诊断 {#diagnosis}
先判断该代码是否来自有意的 RAISE EXCEPTION,还是函数显式选择了某个领域条件。记录 SQLSTATE、本地化和未本地化严重级别、主报文、详细信息、提示、上下文、源码位置以及调用函数的语句。在 PL/pgSQL 处理器中,SQLSTATE 和 SQLERRM 表示当前异常,GET STACKED DIAGNOSTICS 可以取出其字段。
随后定位函数分支及其事务上下文。自动提交下的失败调用只结束该语句,连接仍可执行下一条命令,代表性案例正是如此。显式事务中的调用通常会让事务进入中止状态,直到客户端执行 ROLLBACK 或回滚到保存点;服务器连接本身不一定终止。
EXCEPTION 子句会改变边界。受保护主体在子事务中运行;主体出错后,主体内对持久数据库状态的修改会先回滚,再执行第一个匹配的条件处理器,块外的修改仍保留。WHEN OTHERS 匹配除 QUERY_CANCELED 和 ASSERT_FAILURE 以外的所有错误,范围很宽,不能用它代替对目标 P0001 路径的识别。
处理 {#response}
当过程确实要暴露通用的 PL/pgSQL RAISE 契约时使用 P0001。如果调用方需要区分校验、冲突、配额或其他业务结果,应选择并记录合适的 SQLSTATE,并补充便于处理的 DETAIL 或 HINT。不要为了简化应用代码就把无关的服务器错误都改成 P0001。
在客户端边界,显式事务需要先回滚后再执行无关命令;如果可以隔离函数调用,则使用保存点。在 PL/pgSQL 中,恢复逻辑明确时优先使用 WHEN raise_exception 或 WHEN SQLSTATE 'P0001' 这样的窄处理器。如果确实需要宽处理器,请先保存 RETURNED_SQLSTATE、MESSAGE_TEXT、PG_EXCEPTION_DETAIL、PG_EXCEPTION_HINT 和上下文,再决定继续还是重新抛出。
自然的 RAISE EXCEPTION 案例可以安全演示,因为它测试的正是预期的 PL/pgSQL 机制。这并不使 P0001 成为服务器故障证据;它是函数明确引发的异常。
版本 {#versions}
目录记录 P0001 存在于锁定的 8.0.0–8.4.22 pre-9.0 正式源码、9.0.23 至 18.6 的全部正式快照及 19 Beta 3 预览快照。同 tag 的 REL8_1_4 errcodes.sgml 表已经列出 P0001 和条件名 raise_exception,因此至少可以确认 8.1.4 已有该条件名。9.0 头文件视图中的类标题为 PL/pgSQL Error (PostgreSQL-specific error class),到 9.1 的文本定义变为 PL/pgSQL Error。7.0–7.3 仍有候选源码缺口;这些是目录观察边界,不是实现引入日期的断言。
18.6 固定源码 commit 为 724edf9bde9d356724ad384a2e196edc3c9f80f7。默认 RAISE EXCEPTION 规则有 PostgreSQL 18 文档和 18.6 执行器源码两方面依据。代表性案例在 PostgreSQL 18.6 和 10.21 上通过;它没有覆盖每一种自定义代码、处理器或事务模式。
相关 {#related}
P0000 — plpgsql_error 是更宽的 PL/pgSQL 专用类条件。P0002 — no_data_found、P0003 — too_many_rows 和 P0004 — assert_failure 是独立的 P0 条件。25P02 — in_failed_sql_transaction 描述未处理异常中止显式事务后的后续状态。XX000 — internal_error 是服务器内部错误代码,不应作为有意 RAISE 的同义词。
来源 {#sources}
结构化证据记录在公开证据 JSON中。源码记录固定到 PostgreSQL commit 724edf9bde9d356724ad384a2e196edc3c9f80f7;运行记录保留共享注册表、两个目标摘要和 P0001-snippet-registry-final-20260909 运行 ID。
src.errcodes.18.6—errcodes.txtsrc.pl-exec.18.6—pl_exec.cdoc.plpgsql.18— Errors and Messages 与 Error Trappingdoc.protocol.18— Error and Notice Message Fieldsdoc.transactions.18— Transactions
比较版本
SQLSTATE 证据与已记录的运行版本
cases · plpgsql_raise_exception
{
"assertions": [
"SQLSTATE is P0001",
"The custom message is preserved",
"The failed call is isolated to its transaction"
],
"case_id": "plpgsql_raise_exception",
"cleanup": "Drop the function and case schema.",
"has_snippet": true,
"position": 0,
"preconditions": [
"PL/pgSQL is available"
],
"repair": "Use a domain-specific SQLSTATE only when the caller contract requires it; catch and handle the exception at the correct transaction boundary.",
"trigger": "Execute a function containing RAISE EXCEPTION without an explicit SQLSTATE.",
"versions": [
"10",
"18"
]
}claims · identity.class-and-condition
{
"claim_id": "identity.class-and-condition",
"limits": "The directory identifies the condition; it does not say that every application error should use P0001.",
"method": "Read the Class P0 section and P0001 row in the frozen errcodes.txt snapshot.",
"position": 0,
"runtime": [],
"sources": [
"src.errcodes.18.6"
],
"statement": "P0001 is the raise_exception condition in PostgreSQL-specific Class P0, PL/pgSQL Error."
}claims · raise.default-code
{
"claim_id": "raise.default-code",
"limits": "An explicit condition, SQLSTATE, or ERRCODE selects another code; the default applies to an EXCEPTION-level raise.",
"method": "Read the executor's default err_code branch and the official RAISE documentation.",
"position": 1,
"runtime": [],
"sources": [
"src.pl-exec.18.6",
"doc.plpgsql.18"
],
"statement": "A RAISE EXCEPTION with no condition name and no SQLSTATE defaults to raise_exception, P0001."
}claims · raise.levels-and-fields
{
"claim_id": "raise.levels-and-fields",
"limits": "Client and server visibility also depends on message configuration; an explicit SQLSTATE can accompany a lower level.",
"method": "Read the RAISE syntax, level behavior, USING options, and ereport construction.",
"position": 2,
"runtime": [],
"sources": [
"doc.plpgsql.18",
"src.pl-exec.18.6"
],
"statement": "RAISE supports DEBUG, LOG, INFO, NOTICE, WARNING, and EXCEPTION levels; EXCEPTION normally aborts the current transaction, while lower levels generate messages, and USING can supply structured fields."
}claims · raise.handler-subtransaction
{
"claim_id": "raise.handler-subtransaction",
"limits": "The handler's own errors propagate outward, and local variables follow PL/pgSQL's documented handler rules.",
"method": "Read the official error-trapping and subtransaction descriptions.",
"position": 3,
"runtime": [],
"sources": [
"doc.plpgsql.18"
],
"statement": "A PL/pgSQL block with an EXCEPTION clause runs its protected body in a subtransaction; persistent changes made by the body are rolled back before the matching handler runs."
}claims · raise.others-boundary
{
"claim_id": "raise.others-boundary",
"limits": "OTHERS is a broad handler; this claim does not recommend swallowing all errors.",
"method": "Read the condition matching and handler propagation paragraphs.",
"position": 4,
"runtime": [],
"sources": [
"doc.plpgsql.18"
],
"statement": "OTHERS matches every error type except QUERY_CANCELED and ASSERT_FAILURE, and a new error raised by the selected handler is not caught by that same clause."
}claims · raise.diagnostics
{
"claim_id": "raise.diagnostics",
"limits": "The exact fields present depend on the raised condition and the client interface.",
"method": "Read the PL/pgSQL exception diagnostics section and the protocol field reference.",
"position": 5,
"runtime": [],
"sources": [
"doc.plpgsql.18",
"doc.protocol.18"
],
"statement": "Inside an exception handler, SQLSTATE and SQLERRM identify the active exception and GET STACKED DIAGNOSTICS can retrieve its fields."
}claims · runtime.raise-case
{
"claim_id": "runtime.raise-case",
"limits": "This is an intentional PL/pgSQL exception case; it does not test custom SQLSTATEs, explicit transactions, or handler recovery.",
"method": "Read the stable case and ordered snippet registry, then compare the case_result diagnostics and follow-up status in both final target summaries and raw records.",
"position": 6,
"runtime": [],
"sources": [
"case-manifest.P0001",
"snippet-registry.P0001.final",
"runtime.P0001-snippet-registry-final-20260909.latest",
"runtime.P0001-snippet-registry-final-20260909.pg10"
],
"statement": "plpgsql_raise_exception returned P0001 with the caller-supplied calibration exception message on PostgreSQL 18.6 and 10.21; both autocommit connections remained IDLE and accepted SELECT 1."
}claims · runtime.transaction-context
{
"claim_id": "runtime.transaction-context",
"limits": "No explicit transaction was run in this P0001 case; handler blocks have the separate subtransaction contract above.",
"method": "Read the transaction contract and compare it with the observed IDLE/follow-up result.",
"position": 7,
"runtime": [],
"sources": [
"doc.transactions.18",
"runtime.P0001-snippet-registry-final-20260909.latest",
"runtime.P0001-snippet-registry-final-20260909.pg10"
],
"statement": "An unhandled EXCEPTION in an explicit transaction normally requires rollback before unrelated commands, while the representative autocommit call leaves the connection usable."
}claims · versions.catalogue-boundary
{
"claim_id": "versions.catalogue-boundary",
"limits": "The pre-9.0 source set is locked through 8.4.22 but candidate source gaps remain for 7.0–7.3; the observed condition-name and class-title changes are not exact implementation introduction dates.",
"method": "Read the manifest snapshot and the same-tag REL8_1_4 errcodes.sgml row for the code; the generated per-code history is a derived view.",
"position": 8,
"runtime": [],
"sources": [
"manifest.P0001",
"doc.errcodes.8.1.4"
],
"statement": "The locked catalogue records P0001 in the 8.0.0–8.4.22 pre-9.0 formal sources, every listed formal snapshot from 9.0.23 through 18.6, and 19beta3. The same-tag REL8_1_4 errcodes.sgml row already lists P0001 as raise_exception, confirming that condition-name observation by 8.1.4. The class title changes between the 9.0 header and 9.1 text definitions; candidate source gaps remain for 7.0–7.3. These are presence boundaries, not asserted implementation introduction dates."
}messages · message.raise-user
{
"limits": "There is no universal P0001 primary text; the default message when no text is supplied is the condition name or SQLSTATE.",
"message_id": "message.raise-user",
"path": "",
"position": 0,
"raw": {
"id": "message.raise-user",
"limits": "There is no universal P0001 primary text; the default message when no text is supplied is the condition name or SQLSTATE.",
"primary_template": "caller-supplied RAISE format, condition, or MESSAGE expression",
"severity_source": "default EXCEPTION level",
"sources": [
"src.pl-exec.18.6",
"doc.plpgsql.18"
],
"sqlstate": "P0001"
},
"severity": "default EXCEPTION level",
"sources": [
"src.pl-exec.18.6",
"doc.plpgsql.18"
],
"templates": [
{
"kind": "primary",
"literal": "caller-supplied RAISE format, condition, or MESSAGE expression",
"position": 0,
"role": "",
"template": "caller-supplied RAISE format, condition, or MESSAGE expression"
}
]
}messages · message.runtime-calibration
{
"limits": "This literal is specific to the representative function and is not a built-in P0001 message template.",
"message_id": "message.runtime-calibration",
"path": "",
"position": 1,
"raw": {
"id": "message.runtime-calibration",
"limits": "This literal is specific to the representative function and is not a built-in P0001 message template.",
"primary_template": "calibration exception",
"severity_source": "EXCEPTION",
"sources": [
"runtime.P0001-snippet-registry-final-20260909.latest",
"runtime.P0001-snippet-registry-final-20260909.pg10"
],
"sqlstate": "P0001"
},
"severity": "EXCEPTION",
"sources": [
"runtime.P0001-snippet-registry-final-20260909.latest",
"runtime.P0001-snippet-registry-final-20260909.pg10"
],
"templates": [
{
"kind": "primary",
"literal": "calibration exception",
"position": 0,
"role": "",
"template": "calibration exception"
}
]
}runtimes · runtime.P0001-snippet-registry-final-20260909.latest · 18.6 (Homebrew) · passed
{
"cases": [
"plpgsql_raise_exception"
],
"limits": "",
"position": 0,
"raw": {
"cases": [
"plpgsql_raise_exception"
],
"id": "runtime.P0001-snippet-registry-final-20260909.latest",
"observed": {
"followup": 1,
"message_primary": "calibration exception",
"severity": "ERROR",
"source_file": "pl_exec.c",
"source_function": "exec_stmt_raise",
"source_line": "3923",
"sqlstate": "P0001",
"status_after_error": "IDLE"
},
"raw": "verify/results/P0001-snippet-registry-final-20260909/latest/raw.jsonl",
"raw_sha256": "f0ce5f0fcbeaeba978fbb959a418c24eac2ec1db2b0393b9bc15f24d3936ed1b",
"run_id": "P0001-snippet-registry-final-20260909",
"server_version": "18.6 (Homebrew)",
"server_version_num": 180006,
"snippet_registry": {
"path": "verify/cases/P0001/snippets.json",
"sha256": "1728525c9f6f073807ce34df0d9a4ee60f1c8bce5179c8bca91c92ca79aa795a"
},
"status": "passed",
"summary": "verify/results/P0001-snippet-registry-final-20260909/latest/summary.json",
"summary_sha256": "6c298799062a8c47fd2eee07194afc0a6e53d7e1ef87639c9f996951f4de3c9b",
"target": "latest"
},
"run_id": "P0001-snippet-registry-final-20260909",
"runtime_id": "runtime.P0001-snippet-registry-final-20260909.latest",
"server_version": "18.6 (Homebrew)",
"status": "passed",
"target": "latest"
}runtimes · runtime.P0001-snippet-registry-final-20260909.pg10 · 10.21 (Debian 10.21-1.pgdg90+1) · passed
{
"cases": [
"plpgsql_raise_exception"
],
"limits": "",
"position": 1,
"raw": {
"cases": [
"plpgsql_raise_exception"
],
"id": "runtime.P0001-snippet-registry-final-20260909.pg10",
"image": "postgres@sha256:b2baf8998630663d21370da06387c950e587071bdd307ee34e661cdcc7442bcc",
"observed": {
"followup": 1,
"message_primary": "calibration exception",
"severity": "ERROR",
"source_file": "pl_exec.c",
"source_function": "exec_stmt_raise",
"source_line": "3337",
"sqlstate": "P0001",
"status_after_error": "IDLE"
},
"raw": "verify/results/P0001-snippet-registry-final-20260909/pg10/raw.jsonl",
"raw_sha256": "4308e016521aed455b575094b061162077e06f83884e53e96074db1d7b144dac",
"run_id": "P0001-snippet-registry-final-20260909",
"server_version": "10.21 (Debian 10.21-1.pgdg90+1)",
"server_version_num": 100021,
"snippet_registry": {
"path": "verify/cases/P0001/snippets.json",
"sha256": "1728525c9f6f073807ce34df0d9a4ee60f1c8bce5179c8bca91c92ca79aa795a"
},
"status": "passed",
"summary": "verify/results/P0001-snippet-registry-final-20260909/pg10/summary.json",
"summary_sha256": "5fe9b2e2a9147aebe3bd43af67cd60ff768dddbbe10ae92bb0a5a6d9dcad230c",
"target": "pg10"
},
"run_id": "P0001-snippet-registry-final-20260909",
"runtime_id": "runtime.P0001-snippet-registry-final-20260909.pg10",
"server_version": "10.21 (Debian 10.21-1.pgdg90+1)",
"status": "passed",
"target": "pg10"
}sources · src.errcodes.18.6
{
"commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
"docs_url": "",
"kind": "",
"location": "lines 487-494",
"path": "src/backend/utils/errcodes.txt",
"position": 0,
"sha256": "6e8de346643ba84aa3c9c6a73360acfc7b2dfb89162c06c08ce9bf5bcd5bbcba",
"source_id": "src.errcodes.18.6",
"tag": "REL_18_6",
"url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/errcodes.txt"
}sources · src.pl-exec.18.6
{
"commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
"docs_url": "",
"kind": "",
"location": "lines 3889-3923, exec_stmt_raise default and ereport",
"path": "src/pl/plpgsql/src/pl_exec.c",
"position": 1,
"sha256": "0df3c70a6bccf6dddf443fb99e152a16a67009827c44a820597e98e585cb8b20",
"source_id": "src.pl-exec.18.6",
"tag": "REL_18_6",
"url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/pl/plpgsql/src/pl_exec.c#L3889-L3923"
}sources · doc.plpgsql.18
{
"commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
"docs_url": "",
"kind": "",
"location": "lines 2815-2860, 2957-2968, 3768-3775, 3836-3858, 4008-4013",
"path": "doc/src/sgml/plpgsql.sgml",
"position": 2,
"sha256": "43d705adbded343336341fd3e34ea8940432e8a8211f737d36ba3041ad0a4a51",
"source_id": "doc.plpgsql.18",
"tag": "PG18-docs",
"url": "https://www.postgresql.org/docs/18/plpgsql-errors-and-messages.html"
}sources · doc.protocol.18
{
"commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
"docs_url": "",
"kind": "",
"location": "lines 6254-6290, severity and diagnostic fields",
"path": "doc/src/sgml/protocol.sgml",
"position": 3,
"sha256": "745339e07ebbc2bb67d98b258e25772ada644ef26011e3cd6b3fcbb435235f89",
"source_id": "doc.protocol.18",
"tag": "PG18-docs",
"url": "https://www.postgresql.org/docs/18/protocol-error-fields.html"
}sources · doc.transactions.18
{
"commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
"docs_url": "",
"kind": "",
"location": "transaction rollback and savepoint behavior",
"path": "doc/src/sgml/xact.sgml",
"position": 4,
"sha256": "b48fbe8bd02ce3d1181a350c88c8baa6e11c73edc90a936e77b180daef328c5c",
"source_id": "doc.transactions.18",
"tag": "PG18-docs",
"url": "https://www.postgresql.org/docs/18/tutorial-transactions.html"
}sources · doc.errcodes.8.1.4
{
"commit": "313a720f95a3f41b59f853786b184f38f82172d9",
"docs_url": "",
"kind": "upstream_source",
"location": "REL8_1_4 table rows 1303-1308",
"path": "doc/src/sgml/errcodes.sgml",
"position": 5,
"sha256": "fdd6f5470b19970d3b60219a44e66b33193647975d346adfe2a98178f706b776",
"source_id": "doc.errcodes.8.1.4",
"tag": "",
"url": "https://github.com/postgres/postgres/blob/313a720f95a3f41b59f853786b184f38f82172d9/doc/src/sgml/errcodes.sgml#L1303-L1308"
}sources · manifest.P0001
{
"commit": "",
"docs_url": "",
"kind": "local_artifact",
"location": "snapshots and definition_blobs entries for the P0001 definition",
"path": "sources/manifest.lock.json",
"position": 6,
"sha256": "1727a275f336988ff96b4f9990a4ca253080f73fc5d316e7def165c8cf3708a8",
"source_id": "manifest.P0001",
"tag": "",
"url": "../sources/manifest.lock.json"
}sources · case-manifest.P0001
{
"commit": "",
"docs_url": "",
"kind": "local_artifact",
"location": "plpgsql_raise_exception",
"path": "verify/cases/P0001/cases.json",
"position": 7,
"sha256": "0976d6bce923e005cd20d0b74ffb82b98793c2136497e4f9b281c9168f3fc2f9",
"source_id": "case-manifest.P0001",
"tag": "",
"url": "../verify/cases/P0001/cases.json"
}sources · snippet-registry.P0001.final
{
"commit": "",
"docs_url": "",
"kind": "local_artifact",
"location": "plpgsql_raise_exception ordered function, call, and followup",
"path": "verify/cases/P0001/snippets.json",
"position": 8,
"sha256": "1728525c9f6f073807ce34df0d9a4ee60f1c8bce5179c8bca91c92ca79aa795a",
"source_id": "snippet-registry.P0001.final",
"tag": "",
"url": "../verify/cases/P0001/snippets.json"
}来源引用
定义来源
center · PostgreSQL 18 · english-manuals:0407dc4e5a74bde39aa00848c070b44f4cbf5c40b84ac0bccb5f9be3e53e3a62
正文语言: zh-Hans · english-manuals:0407dc4e5a74bde39aa00848c070b44f4cbf5c40b84ac0bccb5f9be3e53e3a62