尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

PostgreSQL 整数类型全解析:smallint、integer、bigint 的字节、取值范围与类型推断

PostgreSQL 整数类型全解析:smallint、integer、bigint 的字节、取值范围与类型推断 文档教程知识库【免费下载链接】til:memo: Today I Learned项目地址https://gitcode.com/gh_mirrors/ti/til点击查看免费下载PostgreSQL 内置了三种尺寸的整数类型——smallintint2、integerint4与bigintint8它们分别占用 2、4、8 个字节且全部为有符号整数。本文以本仓库的 integers-in-postgres.md 为主线系统梳理三种整数类型的存储大小、精确取值范围、字面量的自动类型推断规则并结合仓库中 postgres-does-not-support-unsigned-integers.md、checking-the-type-of-a-value.md 等关联笔记深入讲解pg_typeof调试技巧、无符号整数缺失的替代方案以及建表与迁移中的最佳实践。读完你将能准确选择整数列类型、解释pg_typeof的推断结果并规避整数溢出与类型变更陷阱。三种整数类型同族同源尺寸不同PostgreSQL 的整数家族没有种类之分只有尺寸之别。官方名称分别是类型名别名占用字节位宽取值范围smallintint22 字节16 位-32768 32767integerint44 字节32 位-2147483648 2147483647bigintint88 字节64 位-9223372036854775808 9223372036854775807三者都只能表示有符号整数。以 4 字节的integer为例32 位二进制能表示的取值范围是 -2147483648 到 2147483647即全部 4 字节所能容纳的数值同理2 字节的smallint覆盖 -32768 到 327678 字节的bigint覆盖 -9223372036854775808 到 9223372036854775807。值得注意的是别名int2、int4、int8并不仅是文档里的简称它们在系统目录pg_type中就是真实存在的类型名。仓库笔记 types-by-category.md 演示了如何通过数值类型的类别代码N枚举全部数值类型select typname from pg_type where typcategory N; typname ----------------- int8 int2 int4 regproc oid float4 float8 money numeric ... (17 rows)可以看到int8、int2、int4正是pg_type目录中的正式类型名smallint、integer、bigint只是面向用户的 SQL 别名。用 pg_typeof 观察字面量的自动推断正如 integers-in-postgres.md 所强调的虽然列可以被显式限制为特定尺寸的整数但 PostgreSQL 在即席处理整数即 SQL 字面量、表达式中间值时足够聪明默认使用integer仅在必要时才升级为bigint。这一点可以用pg_typeof()函数直接验证。pg_typeof()返回任意表达式在 PostgreSQL 中的实际数据类型是排查类型推断问题最直接的工具详见仓库笔记 checking-the-type-of-a-value.md select pg_typeof(55); pg_typeof ----------- integer select pg_typeof(99999999999999999); pg_typeof ----------- bigint字面量55落在integer的范围内于是被推断为integerint4而99999999999999999约 10^17明显超出 32 位有符号整数上限 2147483647PostgreSQL 自动将其推断为bigintint8。这正是默认integer必要时才bigint这一策略的直观体现——字面量的推断完全由数值大小驱动。pg_typeof还能揭示一些细微行为。例如对一个字符串字面量调用它PostgreSQL 暂时无法判定该用text还是varchar会返回unknown select pg_typeof(hello); pg_typeof ----------- unknown此时只需显式标注目标类型即可得到确定结果 select pg_typeof(hello::varchar); pg_typeof ------------------- character varying同理如果你想强制一个超出integer范围的数值在计算中被当作smallint尽管会溢出或用显式类型让字面量按预期宽度参与运算都可以借助::int2、::int4、::int8这类类型转换语法。没有无符号整数范围限制与替代方案由于三种整数类型全部是有符号的PostgreSQL 并不提供 MySQL 那样的UNSIGNED修饰符。仓库笔记 postgres-does-not-support-unsigned-integers.md 专门讨论了这一点以integer为例我们只能存储 -2147483648 到 2147483647 之间的数值——这是 4 字节所能容纳的全部。若系统支持 4 字节无符号整数理论上可以从 0 一直表示到 4294967295。这意味着如果你原本指望数据类型本身来强制某列数据非负比如商品数量、访问计数在 PostgreSQL 中必须另想办法。该笔记给出了两个常见方案CHECK 约束直接为列添加非负校验例如create table inventory ( quantity integer check (quantity 0) );自定义 DOMAIN 类型创建一个限制合法取值的用户定义域类型例如create domain non_negative_int as integer check (value 0);不过该笔记作者的评价是使用域类型的交互方式有些笨拙不值得为此投入精力。需要特别提醒的是无论 CHECK 约束还是 DOMAIN 类型都只是近似模拟无符号整数——它们并没有真正扩大取值范围。也就是说即使加上check (value 0)integer列的最大值依然是 2147483647而不是无符号版的 4294967295。如果你的业务数据可能超过有符号上限正确做法是直接选用更大的整数类型如bigint而不是靠约束挤出高位。建表实践主键与常用整数列理解三种整数类型的字节与范围后建表时的选择就清晰了。仓库笔记 create-a-composite-primary-key.md 展示了整数作为外键与主键组成部分的典型用法create table plane_tickets ( passenger_id integer references passengers not null, flight_id integer references flights not null, confirmation_number varchar(6) not null, seat_assignment varchar not null, primary key (passenger_id, flight_id) );这里的外键列都使用了默认的integer——对于绝大多数业务主键数据量在 21 亿以内它完全够用而且 4 字节比bigint的 8 字节在存储和索引上更省空间。至于自增主键仓库笔记 generate-modern-primary-key-columns.md 给出了一条重要建议serial/bigserial已经过时PostgreSQL 官方 wiki 明确 Dont use serial新应用应优先使用 identity 列。它对比了两种写法传统serial写法不推荐create table books ( id serial primary key, title text not null, author text not null, created_at timestamptz not null default now(), updated_at timestamptz not null default now() );现代 identity 列写法推荐create table books ( id int primary key generated always as identity, title text not null, author text not null, created_at timestamptz not null default now(), updated_at timestamptz not null default now() );如果预计行数会超过 21 亿则应把主键列换成bigint或bigint generated always as identity。类型迁移从 int 到 bigint 何时需要 USING当业务规模增长、integer不再够用时常见操作是把列升级为bigint。仓库笔记 switch-non-castable-column-type-with-using-clause.md 指出从int到bigint属于可以自动类型转换cast的变更PostgreSQL 知道如何原地转换现有数据因此可以直接执行alter table users alter column id set data type bigint;之所以不需要using子句是因为整数类型之间的加宽转换int2→int4→int8是无损且内建的PostgreSQL 能自动完成。与之对比int到uuid这类不存在内建转换路径的变更就必须显式提供using子句告诉数据库如何生成新值alter table users alter column id set data type uuid using (gen_random_uuid());因此当你规划把id从int扩成bigint这样的迁移时可以直接使用上面的alter column ... set data type语句PostgreSQL 会负责把既有数据的类型安全地加宽。小结与选型建议围绕本仓库 integers-in-postgres.md 的核心内容可以总结出以下要点PostgreSQL 只有三种尺寸的整数smallint2 字节±32767、integer4 字节±2147483647、bigint8 字节±9223372036854775807别名分别为int2、int4、int8三者均为有符号整数PostgreSQL不支持无符号整数非负约束需用 CHECK 约束或 DOMAIN 类型近似实现且无法扩大取值范围在即席表达式字面量中PostgreSQL 默认推断为integer超出其范围才升级为bigint可用pg_typeof()验证建表选型时常规主键与计数用integer即可高容量场景选用bigint新应用主键优先使用generated always as identity而非serialint→bigint属于自动可转换的类型变更可直接通过alter column ... set data type完成无需using子句。掌握了这些字节与范围知识你就能在设计表结构时做出精准取舍也能在面对pg_typeof的输出、溢出告警或类型迁移需求时快速定位问题。赞分享文档教程知识库【免费下载链接】til:memo: Today I Learned项目地址https://gitcode.com/gh_mirrors/ti/til点击查看免费下载相关推荐Maka WorkHub Coordination Session不用第二套数据库如何实现持久协调层Maka WorkHub Coordination Session不用第二套数据库如何实现持久协调层 在 Maka 仓库中WorkHub工作中枢需要一人工智能AI Agent自主智能体工具调用交互助手AI 评测TypeScript 中从值推导类型类型推断、字面量收窄与 typeof 提取实践TypeScript 中从值推导类型类型推断、字面量收窄与 typeof 提取实践 导读 type from value Type à partir du文档教程Ruff ty 类型系统深度解析Integer Literal 整数字面量类型的语义与实战Ruff ty 类型系统深度解析Integer Literal 整数字面量类型的语义与实战 整数字面量类型Integer Literal Type是静态类开发工具Lint格式化静态分析CLI上一篇终极小米运动自动刷步数完整指南轻松实现微信支付宝步数同步下一篇如何快速掌握OpenRPA企业级自动化工具的完整实战指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表