↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

Wiki / SQLSTATE

22012 — division_by_zero

除法或取模运算遇到零除数。

英文手册覆盖始于 PostgreSQL 8.1. 来源历史与运行验证各自保留独立版本边界。

当前阅读 PG 18·选择有来源记录的版本

aliases
未知
class name
Data Exception
condition name
division_by_zero
lang
en
sqlstate
22012

版本定义 PG 18

速览 {#at-a-glance}

除法或取模操作遇到零除数。PostgreSQL 18.6 在 numeric、整数、浮点、money 和 interval 除法路径中使用 SQLSTATE 22012,但每条路径仍有自己的操作数和特殊值规则。

SELECT 10::numeric / 0::numeric;
SELECT 10::numeric / 2::numeric;

保留的 PostgreSQL 18.6 和 10.21 实测显示,第一条语句返回 primary division by zero 与 SQLSTATE 22012,随后修正语句返回 5.0000000000000000;修复动作后两个后端均为 IDLE。公开案例 JSON 说明了这个 numeric 除法案例;它不是对下面所有生产路径的运行时比较。

含义 {#meaning}

直接的 numeric_div 和 numeric_mod 会检查 numeric 零除数;内部 *_opt_error 形式也可以设置 have_error 标志并返回 NULL,由调用者自行处理。整数除法和取模函数在使用 / 或 % 前检查第二个操作数是否为零。float4/float8 除法经过 float*_div,当分子不是 NaN 且除数为零时抛错。money 除法检查整数或 money 除数,interval 除法检查浮点因子。这些路径共享 SQLSTATE 和 primary 文本,但实际解析出的运算符及特殊值仍决定结果。

诊断 {#diagnosis}

在运算符和类型解析完成后定位除数或取模除数;不要把 int4 规则推广到全部数值类型。检查零是否来自输入、连接、聚合或业务规则,并阅读完整 primary。NULL 操作数通常在严格算术函数调用前得到 NULL;NULLIF(denominator, 0) 则是有意把零情况变为 NULL。CASE 可以选择 NULL、替代值或跳过分支,因此应选择符合业务结果的分支,不要静默地把错误改成另一个值。

还要区分规划期和执行期:PostgreSQL 18.6 的条件表达式文档警告,常量 1/0 子表达式即使位于运行时不会进入的 CASE 分支,也可能在规划期失败。规划器源码会递归简化常量参数并计算不可变的常量表达式。若必须延迟到执行期,应使用非恒定值,或在实际除数处使用 NULLIF/合适的 CASE;这不能让无效常量表达式变安全,也不能替应用决定 NULL 或替代值哪一种语义正确。

处理 {#response}

修正产生零除数的来源,或明确选择零值策略。只有 NULL 结果符合业务含义时才使用 NULLIF;应用确有替代值或跳过规则时使用 CASE,然后检查下游聚合和过滤将看到的新结果。不要重放未改变的操作。普通固定路径抛出 ERROR;显式事务需先 ROLLBACK 或 ROLLBACK TO SAVEPOINT 再重试,自动提交只重试修正后的动作。保留的 18.6/10.21 numeric 实测仅覆盖这个案例。

报文 {#messages}

  • Primary,ERROR:division by zero。
  • 引用的 numeric、整数、浮点、money 和 interval 除法 guard 没有固定 DETAIL 或 HINT。内部 numeric have_error 调用是软处理路径,不能据此声称直接 SQL 运算成功返回。

版本 {#versions}

锁定目录从 7.4 起记录该条件;固定源码覆盖 PostgreSQL 18.6。保留的 numeric 运行记录是 PostgreSQL 18.6 和 10.21,仅覆盖 10::numeric / 0::numeric 后接 10::numeric / 2::numeric。

相关 {#related}

22003、22008、22015

来源 {#sources}

结构化证据记录保留两份运行摘要/原始摘要哈希和固定源码声明。

比较版本

SQLSTATE 证据与已记录的运行版本

cases · division_by_zero_numeric
{
  "assertions": [
    "SQLSTATE is 22012 with primary division by zero",
    "The failed autocommit session remains IDLE",
    "A nonzero denominator returns the defined numeric result"
  ],
  "case_id": "division_by_zero_numeric",
  "cleanup": "Close the runner connection and drop the case schema with an owner connection.",
  "has_snippet": true,
  "position": 0,
  "preconditions": [
    "A runner-owned disposable target is provisioned."
  ],
  "repair": "Validate the denominator or apply an explicitly chosen domain policy; do not silently turn a calculation into NULL with NULLIF unless that is the intended business result.",
  "trigger": "Evaluate a numeric expression with a zero denominator.",
  "versions": [
    "10",
    "18"
  ]
}
claims · identity
{
  "claim_id": "identity",
  "limits": "",
  "method": "Read the fixed errcodes row and macro.",
  "position": 0,
  "runtime": [],
  "sources": [
    "src.errcodes.18.6"
  ],
  "statement": "22012 is division_by_zero in SQLSTATE Class 22."
}
claims · numeric-divmod
{
  "claim_id": "numeric-divmod",
  "limits": "",
  "method": "Read the complete numeric division and modulo functions.",
  "position": 1,
  "runtime": [],
  "sources": [
    "src.numeric-div.18.6",
    "src.numeric-mod.18.6"
  ],
  "statement": "Numeric division and modulo guard zero divisors; direct SQL calls raise, while internal opt-error forms can report through a have_error soft path."
}
claims · integer-divmod
{
  "claim_id": "integer-divmod",
  "limits": "",
  "method": "Read the representative integer and bigint guards.",
  "position": 2,
  "runtime": [],
  "sources": [
    "src.int-div.18.6",
    "src.int-mod.18.6",
    "src.int8-div.18.6",
    "src.int8-mod.18.6"
  ],
  "statement": "The int4 and int8 division and modulo functions check their second operand before using the arithmetic operator."
}
claims · float-guard
{
  "claim_id": "float-guard",
  "limits": "",
  "method": "Read the exact val2==0 and !isnan(val1) guard.",
  "position": 3,
  "runtime": [],
  "sources": [
    "src.float-inline.18.6",
    "src.float-error.18.6"
  ],
  "statement": "float4/float8 division raises for a zero divisor only when the numerator is not NaN, through the inline zero-divide helper."
}
claims · money-and-interval
{
  "claim_id": "money-and-interval",
  "limits": "",
  "method": "Read the type-specific division guards.",
  "position": 4,
  "runtime": [],
  "sources": [
    "src.cash-int.18.6",
    "src.cash-money.18.6",
    "src.interval-div.18.6"
  ],
  "statement": "Money division checks its divisor and interval division rejects a zero factor with the same condition."
}
claims · planner-boundary
{
  "claim_id": "planner-boundary",
  "limits": "This is a planning/execution boundary, not an assertion that every CASE expression is evaluated early.",
  "method": "Read the planner evaluation path and same-tag documentation.",
  "position": 5,
  "runtime": [],
  "sources": [
    "src.planner-const.18.6",
    "src.docs-conditional.18.6"
  ],
  "statement": "The planner can evaluate an immutable constant division while simplifying expressions; same-tag conditional-expression documentation calls out unreachable CASE 1/0 as a planning-time failure boundary."
}
claims · runtime.observation
{
  "claim_id": "runtime.observation",
  "limits": "The observation covers this numeric case and does not generalize to every producer.",
  "method": "Read both retained summaries, raw digests, and the fixed snippet registry.",
  "position": 6,
  "runtime": [],
  "sources": [
    "runtime.22012-data-runtime-latest.latest",
    "runtime.22012-data-runtime-pg10.pg10",
    "snippet-registry.22012"
  ],
  "statement": "The retained numeric division case observed 22012 for 10::numeric / 0::numeric and 5.0000000000000000 after 10::numeric / 2::numeric on PostgreSQL 18.6 and 10.21; both repaired sessions were IDLE."
}
claims · history
{
  "claim_id": "history",
  "limits": "",
  "method": "Use catalogue presence and history boundaries.",
  "position": 7,
  "runtime": [],
  "sources": [
    "src.errcodes.18.6"
  ],
  "statement": "The locked catalogue records 22012 from 7.4 without proving an exact implementation introduction date."
}
messages · message.division-by-zero
{
  "limits": "Direct cited guards; special values and internal numeric soft callers are type/context dependent.",
  "message_id": "message.division-by-zero",
  "path": "",
  "position": 0,
  "raw": {
    "id": "message.division-by-zero",
    "limits": "Direct cited guards; special values and internal numeric soft callers are type/context dependent.",
    "primary_template": "division by zero",
    "severity_source": "ERROR",
    "sources": [
      "src.numeric-div.18.6",
      "src.numeric-mod.18.6",
      "src.int-div.18.6",
      "src.int-mod.18.6",
      "src.int8-div.18.6",
      "src.int8-mod.18.6",
      "src.float-inline.18.6",
      "src.float-error.18.6",
      "src.cash-int.18.6",
      "src.cash-money.18.6",
      "src.interval-div.18.6"
    ],
    "sqlstate": "22012"
  },
  "severity": "ERROR",
  "sources": [
    "src.numeric-div.18.6",
    "src.numeric-mod.18.6",
    "src.int-div.18.6",
    "src.int-mod.18.6",
    "src.int8-div.18.6",
    "src.int8-mod.18.6",
    "src.float-inline.18.6",
    "src.float-error.18.6",
    "src.cash-int.18.6",
    "src.cash-money.18.6",
    "src.interval-div.18.6"
  ],
  "templates": [
    {
      "kind": "primary",
      "literal": "division by zero",
      "position": 0,
      "role": "",
      "template": "division by zero"
    }
  ]
}
runtimes · runtime.22012-data-runtime-latest.latest · 18.6 (Homebrew) · passed
{
  "cases": [
    "division_by_zero_numeric"
  ],
  "limits": "",
  "position": 0,
  "raw": {
    "cases": [
      "division_by_zero_numeric"
    ],
    "id": "runtime.22012-data-runtime-latest.latest",
    "observed": {
      "sqlstate": "22012",
      "status_after_repair": "IDLE"
    },
    "raw": "verify/results/22012-data-runtime-latest/latest/raw.jsonl",
    "raw_sha256": "9d7035f924444adf1fa68308787310083c584343376d7b041e803a3bd2e1b539",
    "run_id": "22012-data-runtime-latest",
    "server_version": "18.6 (Homebrew)",
    "server_version_num": 180006,
    "snippet_registry": {
      "path": "verify/cases/22012/snippets.json",
      "sha256": "d070ef39a492c0411c3fc2cf9cc841321cae85cbd8a2f8d169f49ecbadbd3be7"
    },
    "status": "passed",
    "summary": "verify/results/22012-data-runtime-latest/latest/summary.json",
    "summary_sha256": "a92ed17a37d32b0a6dc3f30c2b900f4d643fa0dea2736110b1d6170ccba4157c",
    "target": "latest"
  },
  "run_id": "22012-data-runtime-latest",
  "runtime_id": "runtime.22012-data-runtime-latest.latest",
  "server_version": "18.6 (Homebrew)",
  "status": "passed",
  "target": "latest"
}
runtimes · runtime.22012-data-runtime-pg10.pg10 · 10.21 (Debian 10.21-1.pgdg90+1) · passed
{
  "cases": [
    "division_by_zero_numeric"
  ],
  "limits": "",
  "position": 1,
  "raw": {
    "cases": [
      "division_by_zero_numeric"
    ],
    "id": "runtime.22012-data-runtime-pg10.pg10",
    "observed": {
      "sqlstate": "22012",
      "status_after_repair": "IDLE"
    },
    "raw": "verify/results/22012-data-runtime-pg10/pg10/raw.jsonl",
    "raw_sha256": "e8b465904879a89b453d291d4cabddcfe8920ea8c9752f83213644e84f6510f2",
    "run_id": "22012-data-runtime-pg10",
    "server_version": "10.21 (Debian 10.21-1.pgdg90+1)",
    "server_version_num": 100021,
    "snippet_registry": {
      "path": "verify/cases/22012/snippets.json",
      "sha256": "d070ef39a492c0411c3fc2cf9cc841321cae85cbd8a2f8d169f49ecbadbd3be7"
    },
    "status": "passed",
    "summary": "verify/results/22012-data-runtime-pg10/pg10/summary.json",
    "summary_sha256": "60991b51352ba0c2294f65719ada02e39aba969e7467755b138febedcd548e50",
    "target": "pg10"
  },
  "run_id": "22012-data-runtime-pg10",
  "runtime_id": "runtime.22012-data-runtime-pg10.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": "upstream_source",
  "location": "",
  "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#L182"
}
sources · src.numeric-div.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/utils/adt/numeric.c",
  "position": 1,
  "sha256": "6cde7cd60b3330b83be35d1f014045f5fb5fe737f3c5db4c8ed4080b99f2b666",
  "source_id": "src.numeric-div.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/adt/numeric.c#L3243-3375"
}
sources · src.numeric-mod.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/utils/adt/numeric.c",
  "position": 2,
  "sha256": "6cde7cd60b3330b83be35d1f014045f5fb5fe737f3c5db4c8ed4080b99f2b666",
  "source_id": "src.numeric-mod.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/adt/numeric.c#L3467-3553"
}
sources · src.int-div.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/utils/adt/int.c",
  "position": 3,
  "sha256": "ed5a4718016a9acaf68eb08d97bb5c8973c450444dca57e0b953d11c99695e77",
  "source_id": "src.int-div.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/adt/int.c#L861-875"
}
sources · src.int-mod.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/utils/adt/int.c",
  "position": 4,
  "sha256": "ed5a4718016a9acaf68eb08d97bb5c8973c450444dca57e0b953d11c99695e77",
  "source_id": "src.int-mod.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/adt/int.c#L1158-1184"
}
sources · src.int8-div.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/utils/adt/int8.c",
  "position": 5,
  "sha256": "da4d3688c0b037346f25419ea31020af9fec54021f182370234dcbf70b748f36",
  "source_id": "src.int8-div.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/adt/int8.c#L503-517"
}
sources · src.int8-mod.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/utils/adt/int8.c",
  "position": 6,
  "sha256": "da4d3688c0b037346f25419ea31020af9fec54021f182370234dcbf70b748f36",
  "source_id": "src.int8-mod.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/adt/int8.c#L559-588"
}
sources · src.float-inline.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/include/utils/float.h",
  "position": 7,
  "sha256": "e41d97d3eff1ee8447f56562cdf649733330b56f07ee3d81325ee096ff5fd446",
  "source_id": "src.float-inline.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/include/utils/float.h#L222-250"
}
sources · src.float-error.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/utils/adt/float.c",
  "position": 8,
  "sha256": "58914ae93c06c281e581a4bb2dcf2280e4ae1619f3ceb8f801f50beca87eecd8",
  "source_id": "src.float-error.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/adt/float.c#L101-106"
}
sources · src.cash-int.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/utils/adt/cash.c",
  "position": 9,
  "sha256": "a6b9d7af9e8d697b737a5ed5ae98226ed317ec75c06f3fb2dcb057a6bd6a92b3",
  "source_id": "src.cash-int.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/adt/cash.c#L155-161"
}
sources · src.cash-money.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/utils/adt/cash.c",
  "position": 10,
  "sha256": "a6b9d7af9e8d697b737a5ed5ae98226ed317ec75c06f3fb2dcb057a6bd6a92b3",
  "source_id": "src.cash-money.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/adt/cash.c#L728-744"
}
sources · src.interval-div.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/utils/adt/timestamp.c",
  "position": 11,
  "sha256": "2614ccd2182fa904b4cac9bef43039e90a1af578d2d1c6803d49a07420d168f2",
  "source_id": "src.interval-div.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/adt/timestamp.c#L3759-3776"
}
sources · src.planner-const.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/optimizer/util/clauses.c",
  "position": 12,
  "sha256": "7268380af5eccec9e3bf90179f0a2753a7f50426d62af143a451b7f0fb542732",
  "source_id": "src.planner-const.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/optimizer/util/clauses.c#L2437-2462"
}
sources · src.docs-conditional.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "doc/src/sgml/func.sgml",
  "position": 13,
  "sha256": "05d03f505dc3c3b4fb2b3a6e8ed3275c425306a8ff20dd9548e838c26bbb968a",
  "source_id": "src.docs-conditional.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/doc/src/sgml/func.sgml#L20143-20150"
}
sources · snippet-registry.22012
{
  "commit": "",
  "docs_url": "",
  "kind": "local_artifact",
  "location": "",
  "path": "verify/cases/22012/snippets.json",
  "position": 14,
  "sha256": "d070ef39a492c0411c3fc2cf9cc841321cae85cbd8a2f8d169f49ecbadbd3be7",
  "source_id": "snippet-registry.22012",
  "tag": "",
  "url": ""
}

来源引用

完整定义与证据 JSON

定义来源

center · PostgreSQL 18 · english-manuals:a0197ca4c78bba14db70bfeb414095e7f3af9c62c7e232f47480d9ca02d3ef24

正文语言: zh-Hans · english-manuals:a0197ca4c78bba14db70bfeb414095e7f3af9c62c7e232f47480d9ca02d3ef24