☰
PostgreSQL interval 类型五种定义方式详解:从字面量到 make_interval 构建函数
2026/10/8 7:10:02 网站建设 项目流程
  • 文档
  • 教程
  • 知识库

【免费下载链接】til

:memo: Today I Learned

项目地址:https://gitcode.com/gh_mirrors/ti/til
点击查看免费下载

本文围绕 til 仓库 中 PostgreSQL 分类下的实战笔记 different-ways-to-define-an-interval.md,系统梳理interval数据类型的全部常见定义途径。interval用于表示一段离散的时间跨度,是日期运算(date math)的核心工具。读完本文,你将掌握关键字字面量、类型转换、@运算符与make_interval函数这四种定义方式,并能理解它们的等价关系、语法陷阱与适用场景,直接应用到日常 SQL 的时间偏移与筛选逻辑中。

interval 是什么:离散时间跨度的表示

PostgreSQL 的interval类型用于表示一个离散的时间段(a discrete chunk of time),例如"3 天""2 小时 30 分钟""1 年 2 个月"。它不同于timestamp(某个时刻点),也不同于date(某个日历日),它描述的是"多久",因此特别适合做日期运算:给一个时刻加上或减去一段间隔,得到另一个时刻。

这个价值在仓库其他笔记中有大量实战印证:

  • using-intervals-to-offset-time.md 展示了用now() - '2 hours'::interval或now() - interval '2 hours'求"两小时前"的时刻;
  • idempotent-inserts.md 在幂等插入的去重条件里使用created_at > (now() - '3 months'::interval)圈定最近三个月;
  • output-explain-query-plan-in-different-formats.md 用now() - '1 year'::interval构造一年的时间窗来观察执行计划。

可以看到,interval 一旦和now()、timestamp结合,就能以极简洁的写法完成相对时间运算,这也是本文讨论的四种定义方式最直接的应用场景。

方式一:interval 关键字 + 字符串字面量

最直观的定义方式是用interval关键字紧跟一段字符串,字符串内部使用 PostgreSQL 可识别的单位与数量:

> select interval '3 days'; interval ---------- 3 days (1 row)

字符串支持多种自然语言式的组合,例如interval '1 year 2 months 3 days'、interval '2 hours 30 minutes'。PostgreSQL 会解析字符串中形如<数字> <单位>的片段,单位可以是 year、month、day、hour、minute、second 及其复数形式,甚至week。仓库中的 intervals-of-time-by-week.md 就专门演示了周粒度的写法:select '2 weeks'::interval返回14 days,说明周会被统一换算成天数存储。

适用场景:可读性最好,适合手写 SQL、代码评审与临时查询,也是大多数人第一眼能看懂的写法。

方式二:字符串显式转换(::interval)

使用 PostgreSQL 的强制转换语法,把字符串字面量转换为interval类型,效果与方式一完全等价:

> select '3 days'::interval; interval ---------- 3 days (1 row)

::interval本质是调用interval的字符串输入函数(interval_in)完成解析,因此'3 days'::interval与interval '3 days'得到的是同一个值。它比关键字写法更灵活的一点是:可以用在任意表达式位置。例如仓库笔记 using-intervals-to-offset-time.md 中:

> select now() - '2 hours'::interval as earlier; earlier ------------------------------- 2015-06-12 21:17:43.678822-05

适用场景:需要把常量写进复杂表达式、或让字面量的类型意图在运算式中明确可见时,推荐优先使用::interval,可以避免运算符两侧类型不明确导致的隐式转换意外。

方式三:@运算符(需谨慎的冷门语法)

PostgreSQL 还保留了一个@前缀运算符,可以用于声明 interval:

> select @ 3 days; days ------ 3 (1 row)

注意两点:

  1. @ 3 days的结果列名是days,输出值只有数字3,与interval '3 days'的显示形态不同;
  2. 这个语法对空格与格式相当挑剔(原文档称之为 "finicky"),一旦写法不标准很容易触发语法错误,且它依赖上下文中的单位词(如 days)才能被解析。

因此不建议在正式代码中使用。它的存在更多是历史兼容性的体现,日常开发请优先使用前两种方式或make_interval函数。

方式四:make_interval() 函数(参数化构建)

make_interval是 PostgreSQL 提供的专门用于程序化构建 interval 的函数,位于 官方日期时间函数文档 的Interval小节(原文档中亦以此作为参考来源)。它通过具名参数(named arguments)明确指定各个时间分量:

> select make_interval(days => 3); make_interval --------------- 3 days (1 row)

函数签名包含 7 个可选参数(均可省略,省略即按 0 处理),按位置顺序为:

参数含义默认值
years年0
months月0
weeks周0
days天0
hours小时0
mins分钟0
secs秒0

由于参数众多,具名参数(days => 3)是最清晰、最不容易出错的调用方式。如果使用位置参数,则必须把前面的参数也写全。仓库 intervals-of-time-by-week.md 中给出了位置参数调用的实例:

> select make_interval(0,0,7,0,0,0,0); make_interval --------------- 49 days (1 row)

这里的第 3 个参数weeks => 7会被换算为 7 周即 49 天,印证了 interval 内部以"天"为存储单位的换算规则。

适用场景:当间隔的长度在运行时由程序计算得出(例如来自应用层变量或查询参数)时,用make_interval(days => n)这种参数化写法比拼接字符串更安全、更易读,也能完全避免字符串解析的边界问题。

四种方式对比与选择建议

定义方式写法示例可读性是否推荐
interval关键字 + 字符串interval '3 days'最高推荐,日常首选
字符串强制转换'3 days'::interval高推荐,表达式内使用
@运算符@ 3 days低,语法挑剔不推荐
make_interval()函数make_interval(days => 3)高,参数化明确推荐,动态构建

核心要点:

  • 方式一与方式二在语义上完全等价,都是把字符串交给 interval 的输入解析器,区别只在写法;
  • @运算符仅作为冷门兼容语法存在,实际项目建议避开;
  • make_interval支持年、月、周、天、时、分、秒七个分量的自由组合,是最适合动态构建间隔的手段;
  • 无论用哪种方式定义,得到的都是同一个interval值,可直接参与now() - interval之类的日期运算。

以上四种方式也补充了仓库中 intervals-of-time-by-week.md 与 using-intervals-to-offset-time.md 两篇相关笔记的实践细节,可配合阅读,形成对 PostgreSQL 时间跨度处理的完整认识。

  • 文档
  • 教程
  • 知识库

【免费下载链接】til

:memo: Today I Learned

项目地址:https://gitcode.com/gh_mirrors/ti/til
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询