PostgreSQL自带了好几个内置函数用来处理当前的时间值。这些函数在比如自动记录创建时间、按当前日期生成报表、或者判断某个事件是不是在指定时间段内发生的时候特别有用。我们来看看三个最常用的函数:NOW()、CURRENT_DATE和CURRENT_TIME。
NOW():获取当前日期和时间
NOW()函数会返回当前的日期和时间,格式是TIMESTAMP WITH TIME ZONE。也就是说,结果里会带上服务器的时区。
例子:
SELECT NOW();
-- 结果: 2025-05-25 14:30:45.761523+03
注意,结果包含:
- 日期(
2025-05-25), - 时间(
14:30:45.761523), - 时区(
+03)。
如果你不想要时区,可以把结果显式转换成TIMESTAMP:
SELECT NOW()::TIMESTAMP;
-- 结果: 2025-05-25 14:30:45.761523
CURRENT_DATE:获取当前日期
CURRENT_DATE函数只会返回当前日期,不带时间。返回值类型是DATE。
例子:
SELECT CURRENT_DATE;
-- 结果: 2025-05-25
如果你只关心日期,比如算年龄、或者按天分组数据,这个就很方便。
CURRENT_TIME:获取当前时间
CURRENT_TIME函数会返回当前时间,格式是TIME WITH TIME ZONE。如果你不需要时区,可以把结果转成TIME。
例子:
SELECT CURRENT_TIME;
-- 结果: 14:30:45.761523+03
SELECT CURRENT_TIME::TIME;
-- 结果: 14:30:45.761523
函数的使用例子
来看看几个实际场景,这些函数怎么用才最顺手。
自动填充记录的创建时间
插入表数据的时候,自动保存创建的日期和时间其实挺常见的。在PostgreSQL里,建表的时候加上DEFAULT NOW()就行了。
建表例子:
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
customer_name TEXT NOT NULL,
created_at TIMESTAMP DEFAULT NOW() -- 插入行的时间
);
插入一条记录:
INSERT INTO orders (customer_name) VALUES ('Otto Lin');
看看表里的内容:
SELECT * FROM orders;
结果:
| id | customer_name | created_at |
|---|---|---|
| 1 | Otto Lin | 2024-11-25 14:45:12.154678 |
按日期过滤数据
假设我们有个订单表,想查今天创建的所有订单。可以用CURRENT_DATE来过滤:
SELECT *
FROM orders
WHERE created_at::DATE = CURRENT_DATE;
这里我们用created_at::DATE把时间去掉,只留日期。
NOW()和CURRENT_TIMESTAMP的区别
乍一看,NOW()和CURRENT_TIMESTAMP好像是一样的。其实确实差不多。只是NOW()和CURRENT_TIMESTAMP分别来自不同的标准。
NOW() — PostgreSQL自带函数
NOW()是PostgreSQL内置函数,返回TIMESTAMP WITH TIME ZONE(timestamptz)类型的值。它表示SQL查询开始时服务器的当前时间。
例子:
SELECT NOW();
CURRENT_TIMESTAMP — SQL标准
CURRENT_TIMESTAMP是SQL标准里定义的表达式,在PostgreSQL里也返回TIMESTAMP WITH TIME ZONE。其实PostgreSQL内部就是把CURRENT_TIMESTAMP当成和NOW()一样的函数来处理。
例子:
SELECT CURRENT_TIMESTAMP;
实际对比
SELECT NOW(), CURRENT_TIMESTAMP;
结果:
| now | current_timestamp |
|---|---|
| 2025-05-25 14:30:45+03 | 2025-05-25 14:30:45+03 |
两个值是一样的,因为它们都是在查询开始时算出来的。
在过滤条件里用时间函数
现在我们来写个查询,查最近7天创建的记录。可以用NOW()和日期运算:
SELECT *
FROM orders
WHERE created_at >= NOW() - INTERVAL '7 days';
同理,如果要查本月的订单,可以用DATE_TRUNC()函数,把时间截到月初:
SELECT *
FROM orders
WHERE created_at >= DATE_TRUNC('month', NOW());
DATE_TRUNC()这个函数挺有意思的,后面几节我会详细讲讲 :P
实用小贴士
- 如果你需要带时区的精确时间,用
NOW()或者CURRENT_TIMESTAMP。 - 只需要日期的话(比如算年龄、分析某天的事件),用
CURRENT_DATE就够了。 CURRENT_TIME一般用在报表或者界面上,显示任务花了多少时间这种场景。
下一节我们会开始用EXTRACT()和AGE()这些函数来提取日期和时间的部分内容。比如可以很方便地算出一个人的年龄,或者按天、月、年处理数据。
GO TO FULL VERSION