表 9.33 显示日期/时间值处理的可用函数,详细内容请参阅以下小节。 表 9.32 说明了基本算术运算符(+
、*
等)的行为。有关格式化函数,请参阅 第 9.8 节。您应该熟悉 第 8.5 节 中有关日期/时间数据类型的背景信息。
此外,表 9.1 中显示的常用比较运算符可用于日期/时间类型。日期和时间戳(带或不带时区)都可比较,而时间(带或不带时区)和间隔只能与相同数据类型的值进行比较。将不带时区的时间戳与带时区的时间戳进行比较时,将假定前者给定在 TimeZone 配置参数指定的时区中,并且将转换为 UTC 以便与后者进行比较(后者在内部已经处于 UTC 中)。同样地,将日期值视为代表 TimeZone
时区中的午夜,然后再将其与时间戳进行比较。
以下描述的所有使用 time
或 timestamp
输入的函数和运算符实际上有两种变体:一种使用 time with time zone
或 timestamp with time zone
,一种使用 time without time zone
或 timestamp without time zone
。为简洁起见,未单独显示这些变体。此外,+
和 *
运算符以交换对的形式出现(例如 date
+
integer
和 integer
+
date
);我们只显示每一对中的一种。
表 9.32。日期/时间运算符
运算符 说明 示例 |
---|
将天数添加到日期中
|
对日期添加间隔
|
在日期中添加时间
|
添加间隔
|
在时间戳中添加间隔
|
在时间中添加间隔
|
否定间隔
|
减去日期,得出已过天数
|
从日期中减去一些天数
|
从日期中减去间隔
|
减去时间
|
从时间中减去间隔
|
从时间戳中减去间隔
|
减去间隔
|
减去时间戳(将 24 小时区间转换为天,类似于
|
使用标量乘以区间
|
使用标量除以区间
|
表 9.33。日期/时间函数
函数 说明 示例 |
---|
减去参数,生成“符号”结果,使用年和月,而不仅仅是天
|
从
|
当前日期和时间(在语句执行过程中发生变化);请参见 第 9.9.5 节
|
当前日期;请参见 第 9.9.5 节
|
当前时间;请参见 第 9.9.5 节
|
当前时间,精度有限;请参见 第 9.9.5 节
|
当前日期和时间(当前事务开始时间);参见 9.9.5 节
|
当前日期和时间(当前事务开始时间),使用小数精度;参见 9.9.5 节
|
向
|
按照与指定起点对齐的指定时间间隔对输入进行划分;参见 9.9.3 节
|
获取时间戳子字段(等效于
|
获取区间子字段(等同于
|
从
|
截断至指定精度;请参阅 第 9.9.2 节
|
在指定时区截断至指定精度;请参阅 第 9.9.2 节
|
截断至指定精度;请参阅 第 9.9.2 节
|
获取时间戳子字段;请参阅 第 9.9.1 节
|
获取区间子字段;请参阅 第 9.9.1 节
|
测试有限日期(非 +/- 无限大)
|
测试有限时间戳(非 +/- 无限大)
|
测试有限间隔(非 +/- 无限大)
|
调整间隔, 将 30 天时间段转换为月
|
调整间隔, 将 24 小时的时间段转换为天
|
使用
|
当前时间;请参见 第 9.9.5 节
|
当前时间,精度有限;请参见 第 9.9.5 节
|
当前日期和时间(当前事务开始时间);参见 9.9.5 节
|
当前日期和时间(当前事务开始时间),使用小数精度;参见 9.9.5 节
|
根据年、月、日字段创建日期(负年表示公元前)
|
根据年、月、周、日、时、分、秒字段创建间隔(每个字段均可默认为零)
|
根据时、分、秒字段创建时间
|
根据年、月、日、时、分、秒字段创建时间戳(负年表示公元前)
|
从年、月、日、小时、分钟和秒字段创建带有时区的 timestamp(负年表示公元前)。如果未指定
|
当前日期和时间(当前事务开始时间);参见 9.9.5 节
|
当前日期和时间(当前语句的开始);参见小节 9.9.5
|
当前日期和时间(类似于
|
当前日期和时间(当前事务开始时间);参见 9.9.5 节
|
将 Unix 纪元(自 1970-01-01 00:00:00+00 起的秒数)转换为带有时区的 timestamp
|
(start1
,end1
) OVERLAPS (start2
,end2
) (start1
,length1
) OVERLAPS (start2
,length2
)
当两个时间段(由其端点定义)重叠时,此表达式返回 true,而当它们不重叠时,此表达式返回 false。端点可以指定为日期对、时间或时间戳对;或者为一个日期、时间或时间戳后跟一个时间间隔。当提供一对儿值时,可以先写开始时间或结束时间;OVERLAPS
会自动将对儿中的较早值作为开始时间。每个时间段都被认为是表示半开区间的 start
<=
time
<
end
,除非 start
和 end
相等,在这种情况下,它表示那个单独的时间瞬时。例如,这意味着端点只有一个公共点的两个时间段不会重叠。
SELECT (DATE '2001-02-16', DATE '2001-12-21') OVERLAPS (DATE '2001-10-30', DATE '2002-10-30'); Result:true
SELECT (DATE '2001-02-16', INTERVAL '100 days') OVERLAPS (DATE '2001-10-30', DATE '2002-10-30'); Result:false
SELECT (DATE '2001-10-29', DATE '2001-10-30') OVERLAPS (DATE '2001-10-30', DATE '2001-10-31'); Result:false
SELECT (DATE '2001-10-30', DATE '2001-10-30') OVERLAPS (DATE '2001-10-30', DATE '2001-10-31'); Result:true
将 interval
值添加到(或从 timestamp
或 timestamp with time zone
值中减去 interval
值)时,将按顺序处理 interval
值的月份、天数和微秒字段。首先,非零月份字段会将时间戳的日期按指示的月份数前进或后退,同时保持月份日不变,除非它会超过新月份的结束时间,在这种情况下将使用该月份的最后一天。(例如,3 月 31 日加 1 个月变成 4 月 30 日,但 3 月 31 日加 2 个月变成 5 月 31 日。)然后天数字段会将时间戳的日期按指示的天数前进或后退。在这两个步骤中,都会保持当地的每日时间不变。最后,如果存在非零微秒字段,则会将其加或减为原文值。对识别夏令时的时区中的 timestamp with time zone
值执行算术运算时,这意味着加或减(例如)interval '1 day'
并不一定与加或减 interval '24 hours'
产生相同的结果。例如,将会话时区设置为 America/Denver
SELECT timestamp with time zone '2005-04-02 12:00:00-07' + interval '1 day'; Result:2005-04-03 12:00:00-06
SELECT timestamp with time zone '2005-04-02 12:00:00-07' + interval '24 hours'; Result:2005-04-03 13:00:00-06
发生这种情况是因为在时区为 America/Denver
的 2005-04-03 02:00:00
处发生了夏令时变化而跳过了一个小时。
请注意,age
返回的 months
字段中可能存在歧义,因为不同的月份有不同的天数。PostgreSQL 的方法是在计算部分月份时使用两个日期中较早的日期的月份。例如,age('2004-06-01', '2004-04-30')
使用 4 月得出 1 mon 1 day
,而使用 5 月会得出 1 mon 2 days
,因为 5 月有 31 天,而 4 月只有 30 天。
日期和时间戳的减法也可能很复杂。一种在概念上简单的执行减法的方法是使用 EXTRACT(EPOCH FROM ...)
将每个值转换为秒数,然后减去结果;这将产生两个值之间的 秒 数。这将根据每个月的天数、时区变化和夏令时调整进行调整。用 “-
” 运算符减去日期或时间戳值返回两个值之间的天数(24 小时数)和小时数/分钟数/秒数,并进行相同的调整。 age
函数返回年数、月数、天数以及小时数/分钟数/秒数,执行逐字段减法,然后根据负字段值进行调整。以下查询说明了这些方法的差异。示例结果使用 timezone = 'US/Eastern'
生成,两个已使用的日期之间有夏令时变化
SELECT EXTRACT(EPOCH FROM timestamptz '2013-07-01 12:00:00') - EXTRACT(EPOCH FROM timestamptz '2013-03-01 12:00:00'); Result:10537200.000000
SELECT (EXTRACT(EPOCH FROM timestamptz '2013-07-01 12:00:00') - EXTRACT(EPOCH FROM timestamptz '2013-03-01 12:00:00')) / 60 / 60 / 24; Result:121.9583333333333333
SELECT timestamptz '2013-07-01 12:00:00' - timestamptz '2013-03-01 12:00:00'; Result:121 days 23:00:00
SELECT age(timestamptz '2013-07-01 12:00:00', timestamptz '2013-03-01 12:00:00'); Result:4 mons
EXTRACT
, date_part
#EXTRACT(field
FROMsource
)
extract
函数从日期/时间值中检索子字段,例如年份或小时。source
必须是类型为 timestamp
、date
、time
或 interval
的值表达式。(时间戳和时间可以带时区,也可以不带时区。)field
是一个标识符或字符串,用于选择要从源值中提取哪个字段。并非所有字段都对每个输入数据类型有效;例如,无法从 date
中提取小于一天的字段,而无法从 time
中提取一天或更长时间的字段。extract
函数返回类型为 numeric
的值。
以下字段名称有效
century
世纪;对于 interval
值,将年字段除以 100
SELECT EXTRACT(CENTURY FROM TIMESTAMP '2000-12-16 12:21:13'); Result:20
SELECT EXTRACT(CENTURY FROM TIMESTAMP '2001-02-16 20:38:40'); Result:21
SELECT EXTRACT(CENTURY FROM DATE '0001-01-01 AD'); Result:1
SELECT EXTRACT(CENTURY FROM DATE '0001-12-31 BC'); Result:-1
SELECT EXTRACT(CENTURY FROM INTERVAL '2001 years'); Result:20
day
这个月的第几天(1-31);对于 interval
值,天数
SELECT EXTRACT(DAY FROM TIMESTAMP '2001-02-16 20:38:40'); Result:16
SELECT EXTRACT(DAY FROM INTERVAL '40 days 1 minute'); Result:40
decade
年字段除以 10
SELECT EXTRACT(DECADE FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 200
dow
星期日 (0
) 到星期六 (6
) 的星期几
SELECT EXTRACT(DOW FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 5
请注意,extract
的星期几编号与 to_char(..., 'D')
函数的星期几编号不同。
doy
这个年份的第几天(1-365/366)
SELECT EXTRACT(DOY FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 47
epoch
对于 timestamp with time zone
值,自 1970-01-01 00:00:00 UTC 以来经过的秒数(在该时间点之前的时戳为负数);对于 date
和 timestamp
值,自 1970-01-01 00:00:00 所经过的秒数(标称),而不考虑时区或夏令时规则;对于 interval
值,间隔内的总秒数
SELECT EXTRACT(EPOCH FROM TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40.12-08'); Result:982384720.120000
SELECT EXTRACT(EPOCH FROM TIMESTAMP '2001-02-16 20:38:40.12'); Result:982355920.120000
SELECT EXTRACT(EPOCH FROM INTERVAL '5 days 3 hours'); Result:442800.000000
你可以使用 to_timestamp
将 epoch 值转换回 timestamp with time zone
SELECT to_timestamp(982384720.12);
Result: 2001-02-17 04:38:40.12+00
须注意,将 to_timestamp
应用于从 date
或 timestamp
值中提取的 epoch 值可能产生误导性结果:结果将有效地假定原始值已在 UTC 中给出,但实际情况可能并非如此。
hour
小时字段(在时间戳中为 0-23,在间隔中不受限制)
SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 20
isodow
星期几,从星期一 (1
) 到星期日 (7
)
SELECT EXTRACT(ISODOW FROM TIMESTAMP '2001-02-18 20:38:40');
Result: 7
这与 dow
相同,只是星期日除外。这与ISO8601 星期几编号相同。
isoyear
日期所在ISO8601 星期编号年份
SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-01'); Result:2005
SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-02'); Result:2006
每个ISO8601 星期编号年份以包含 1 月 4 日的那一周的星期一开始,因此在 1 月初或 12 月末ISO年份可能与公历年份不同。有关详细信息,请参阅 week
字段。
julian
与日期或时间戳相对应的儒略日。不是本地午夜的时间戳将导致分数值。有关详细信息,请参阅B.7 节。
SELECT EXTRACT(JULIAN FROM DATE '2006-01-01'); Result:2453737
SELECT EXTRACT(JULIAN FROM TIMESTAMP '2006-01-01 12:00'); Result:2453737.50000000000000000000
microseconds
秒字段,包括小数部分,乘以 1 000 000;请注意,这包括全秒
SELECT EXTRACT(MICROSECONDS FROM TIME '17:12:28.5');
Result: 28500000
millennium
千年;对于 interval
值,年份字段除以 1000
SELECT EXTRACT(MILLENNIUM FROM TIMESTAMP '2001-02-16 20:38:40'); Result:3
SELECT EXTRACT(MILLENNIUM FROM INTERVAL '2001 years'); Result:2
1900 年代的年份属于第二个千年。第三个千年始于 2001 年 1 月 1 日。
milliseconds
秒字段,包括小数部分,乘以 1000。请注意,这包括全秒。
SELECT EXTRACT(MILLISECONDS FROM TIME '17:12:28.5');
Result: 28500.000
minute
分钟字段(0-59)
SELECT EXTRACT(MINUTE FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 38
month
一年中的月份数量(1-12);对于 interval
值,月份总数模 12(0-11)
SELECT EXTRACT(MONTH FROM TIMESTAMP '2001-02-16 20:38:40'); Result:2
SELECT EXTRACT(MONTH FROM INTERVAL '2 years 3 months'); Result:3
SELECT EXTRACT(MONTH FROM INTERVAL '2 years 13 months'); Result:1
quarter
日期所在的季度(1-4)
SELECT EXTRACT(QUARTER FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 1
second
秒字段,包括所有小数秒
SELECT EXTRACT(SECOND FROM TIMESTAMP '2001-02-16 20:38:40'); Result:40.000000
SELECT EXTRACT(SECOND FROM TIME '17:12:28.5'); Result:28.500000
timezone
从 UTC 偏移的时间,以秒为单位。正值对应于 UTC 以东的时间,负值对应于 UTC 以西的时间。(从技术上讲,PostgreSQL 不使用 UTC,因为不处理闰秒。)
timezone_hour
时区偏移的小时部分
timezone_minute
时区偏移的分钟部分
week
个ISO8601 年周数。根据定义,ISO 周从星期一开始,并且一年的第一周包含该年的 1 月 4 日。换句话说,一年的第一个星期四是该年的第 1 周。
在 ISO 周编号系统中,年初日期可能属于前一年的第 52 周或第 53 周,而年末日期可能属于下一年的第一周。例如,2005-01-01
属于 2004 年的第 53 周,2006-01-01
属于 2005 年的第 52 周,而 2012-12-31
属于 2013 年的第一周。建议将 isoyear
字段与 week
结合使用,以获得一致的结果。
SELECT EXTRACT(WEEK FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 7
年
年份字段。请记住,不存在 公元 0 年
,因此在 公元
年中减去 公元前
年时应小心。
SELECT EXTRACT(YEAR FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 2001
在处理 interval
值时,extract
函数产生与间隔输出函数所用解释相匹配的字段值。如果从一个非标准的间隔表示开始,这可能会产生令人惊讶的结果,例如
SELECT INTERVAL '80 minutes'; Result:01:20:00
SELECT EXTRACT(MINUTES FROM INTERVAL '80 minutes'); Result:20
当输入值是 +/- 无穷大时,extract
返回单调增加的字段(对于 timestamp
输入:epoch
、julian
、year
、isoyear
、decade
、century
和 millennium
;对于 interval
输入:epoch
、hour
、day
、year
、decade
、century
和 millennium
)的 +/- 无穷大。对于其他字段,返回 NULL。9.6 之前的 PostgreSQL 版本在所有无限输入的情况下都返回零。
extract
函数主要用于计算处理。有关显示日期/时间值的格式化,请参阅第 9.8 节。
date_part
函数参照传统 Ingres 等效于SQL- 标准功能 extract
date_part('field
',source
)
请注意,此处 field
参数需要是字符串值,而不是名称。date_part
的有效字段名称与 extract
的相同。出于历史原因,date_part
函数返回类型为 double precision
的值。在某些用法中,这可能导致精度损失。建议改用 extract
。
SELECT date_part('day', TIMESTAMP '2001-02-16 20:38:40'); Result:16
SELECT date_part('hour', INTERVAL '4 hours 3 minutes'); Result:4
date_trunc
#函数 date_trunc
在概念上与数字的 trunc
函数类似。
date_trunc(field
,source
[,time_zone
])
source
是类型 timestamp
、timestamp with time zone
或 interval
的值表达式。(类型为 date
和 time
的值分别自动转换为 timestamp
或 interval
。)field
选择将输入值截断到的精度。返回值也是类型 timestamp
、timestamp with time zone
或 interval
,它具有所有低于所选字段且设置位零(或对于 day 和 month 设置位一)的字段。
field
的有效值是
microseconds |
milliseconds |
second |
minute |
hour |
day |
week |
month |
quarter |
年 |
decade |
century |
millennium |
当输入值类型为 timestamp with time zone
时,截断将根据特定时区进行;例如,截断到 day
会生成该时区的午夜值。默认情况下,截断将根据当前 TimeZone 设置进行,但可提供可选的 time_zone
参数以指定不同的时区。可以在 第 8.5.3 节 中描述的任何一种方式中指定时区名称。
在处理 timestamp without time zone
或 interval
输入时,无法指定时区。这些始终按字面值获取。
示例(假设本地时区是 America/New_York
)
SELECT date_trunc('hour', TIMESTAMP '2001-02-16 20:38:40'); Result:2001-02-16 20:00:00
SELECT date_trunc('year', TIMESTAMP '2001-02-16 20:38:40'); Result:2001-01-01 00:00:00
SELECT date_trunc('day', TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40+00'); Result:2001-02-16 00:00:00-05
SELECT date_trunc('day', TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40+00', 'Australia/Sydney'); Result:2001-02-16 08:00:00-05
SELECT date_trunc('hour', INTERVAL '3 days 02:47:33'); Result:3 days 02:00:00
date_bin
#函数 date_bin
将输入时间戳“分组”到指定的间隔(即 步幅),该间隔与指定原点对齐。
date_bin(stride
,source
,origin
)
source
是类型 timestamp
或 timestamp with time zone
的值表达式。(类型为 date
的值自动转换为 timestamp
。)stride
是类型 interval
的值表达式。返回值也是类型 timestamp
或 timestamp with time zone
,它标记了将 source
放置到的区间的开始。
示例
SELECT date_bin('15 minutes', TIMESTAMP '2020-02-11 15:44:17', TIMESTAMP '2001-01-01'); Result:2020-02-11 15:30:00
SELECT date_bin('15 minutes', TIMESTAMP '2020-02-11 15:44:17', TIMESTAMP '2001-01-01 00:02:30'); Result:2020-02-11 15:32:30
在满单位(1 分钟、1 小时等)的情况下,它给出的结果与类似的 date_trunc
调用相同,但不同之处在于 date_bin
可以截断到任意间隔。
stride
间隔必须大于零,且不能包含 month 或更大的单位。
AT TIME ZONE 和 AT LOCAL
#AT TIME ZONE
运算符将没有时区的 time stamp 转换为有时区的 timestamp,并将 time with time zone
值转换为不同的时区。 表 9.34 显示其变体。
表 9.34. AT TIME ZONE
和 AT LOCAL
变体
运算符 说明 示例 |
---|
将给定的没有时区的 timestamp 转换为有时区的 timestamp,假设给定值处于命名时区中。
|
将给定的没有时区的 timestamp 转换为有会话
|
将给定的有时区的 timestamp 转换为没有时区的 timestamp,因为时间显示在该时区内。
|
将给定的有时区的 timestamp 转换为没有时区的 timestamp,因为时间显示在以会话
|
将给定有时区的 time 转换为新的时区。由于未提供日期,这将使用命名的目标时区的当前有效的 UTC 偏移量。
|
将给定时间 使用 时区转换为一个新时区。由于没有提供日期,这使用会话的 假设会话的
|
在这些表达式中,所需的时区 zone
可以指定为文本值(例如,'America/Los_Angeles'
)或间隔(例如,INTERVAL '-08:00'
)。在文本情况下,可以用以下 第 8.5.3 节 中描述的方式来指定时区名称。间隔情况仅对 UTC 具有固定偏移的区域有用,所以在实际操作中并不常见。
语法 AT LOCAL
可用作 AT TIME ZONE
的简写,其中 local
local
是会话的 TimeZone
值。
范例(假设当前 TimeZone 设置是 America/Los_Angeles
)
SELECT TIMESTAMP '2001-02-16 20:38:40' AT TIME ZONE 'America/Denver'; Result:2001-02-16 19:38:40-08
SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE 'America/Denver'; Result:2001-02-16 18:38:40
SELECT TIMESTAMP '2001-02-16 20:38:40' AT TIME ZONE 'Asia/Tokyo' AT TIME ZONE 'America/Chicago'; Result:2001-02-16 05:38:40
SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT LOCAL; Result:2001-02-16 17:38:40
SELECT TIME WITH TIME ZONE '20:38:40-05' AT LOCAL; Result:17:38:40
第一个范例向不带时区的数值添加一个时区,并使用当前 TimeZone
设置显示该数值。第二个范例将带有时区值的时间戳更改为指定时区,并返回不含时区的该值。这允许存储和显示与当前 TimeZone
设置不同的值。第三个范例将东京时间转换为芝加哥时间。第四个范例将带有时区值的时间戳更改为 TimeZone
设置当前指定的时区,并返回不含时区的该值。
第五个范例是一个警示故事。由于没有日期与输入值关联,因此转换使用会话的当前日期进行。因此,此静态范例可能会根据查看它的时间显示错误的结果,因为 'America/Los_Angeles'
遵守夏令时。
函数
等效于符合 SQL 的结构 timezone
(zone
, timestamp
)
。timestamp
AT TIME ZONE zone
函数
等效于 SQL 一致的结构 timezone
(zone
, time
)
。time
AT TIME ZONE zone
函数
等效于 SQL 一致的结构 timezone
(timestamp
)
。timestamp
AT LOCAL
函数
等效于 SQL 一致的结构 timezone
(time
)
。time
AT LOCAL
PostgreSQL 提供了许多函数,返回与当前日期和时间相关的值。这些 SQL 标准函数都返回基于当前事务开始时间的值
CURRENT_DATE CURRENT_TIME CURRENT_TIMESTAMP CURRENT_TIME(precision
) CURRENT_TIMESTAMP(precision
) LOCALTIME LOCALTIMESTAMP LOCALTIME(precision
) LOCALTIMESTAMP(precision
)
CURRENT_TIME
和 CURRENT_TIMESTAMP
提供带时区的值;LOCALTIME
和 LOCALTIMESTAMP
提供不带时区的值。
CURRENT_TIME
、CURRENT_TIMESTAMP
、LOCALTIME
和 LOCALTIMESTAMP
可以选择使用一个精度参数,该参数会导致结果在秒字段中舍入为那么多小数位。如果没有精度参数,则结果将以全部可用的精度提供。
一些示例
SELECT CURRENT_TIME; Result:14:39:53.662522-05
SELECT CURRENT_DATE; Result:2019-12-23
SELECT CURRENT_TIMESTAMP; Result:2019-12-23 14:39:53.662522-05
SELECT CURRENT_TIMESTAMP(2); Result:2019-12-23 14:39:53.66-05
SELECT LOCALTIMESTAMP; Result:2019-12-23 14:39:53.662522
由于这些函数返回当前事务的开始时间,因此其值在事务期间不会发生更改。这被认为是一个特性:目的是允许单个事务对 “当前”时间有一个一致的概念,以便同一事务内的多次修改带有相同的时间戳。
其他数据库系统可能会更频繁地增加这些值。
PostgreSQL 还提供返回当前语句的开始时间以及函数调用瞬间的实际当前时间的函数。非 SQL 标准时间函数的完整列表为:
transaction_timestamp() statement_timestamp() clock_timestamp() timeofday() now()
transaction_timestamp()
等同于 CURRENT_TIMESTAMP
,但能明显地反映其返回内容,故由此命名。 statement_timestamp()
返回当前语句的开始时间(更准确地说,是接收来自客户端的最新命令消息的时间)。 statement_timestamp()
和 transaction_timestamp()
在事务的第一个命令期间返回相同的值,但在随后的命令中可能会不同。 clock_timestamp()
返回实际当前时间,因此即使在单个 SQL 命令中其值也会发生变化。 timeofday()
是一个历史悠久的 PostgreSQL 函数。与 clock_timestamp()
一样,它返回实际当前时间,但格式化为 text
字符串,而不是 带时区的 timestamp
值。 now()
是 PostgreSQL 中等同于 transaction_timestamp()
的传统函数。
全部日期/时间数据类型还接受特殊文字值 now
,以指定当前日期和时间(同样,解释为事务开始时间)。因此,以下三个函数都返回相同的结果
SELECT CURRENT_TIMESTAMP; SELECT now(); SELECT TIMESTAMP 'now'; -- but see tip below
在指定稍后要计算的值时不要使用第三种形式,例如表列的 DEFAULT
子句中。一旦解析该常量,系统就会将 now
转换为 timestamp
,因此需要默认值时,将使用表创建的时间!前两种形式将推迟到使用默认值时才计算,因为它们是函数调用。因此,它们会实现按行插入时间进行默认设置的预期行为。(另请参见 第 8.5.1.4 节。)
可以使用以下函数延迟服务器进程执行
pg_sleep (double precision
) pg_sleep_for (interval
) pg_sleep_until (timestamp with time zone
)
pg_sleep
使当前会话的进程休眠,直到经过一定秒数。可以指定几分之一秒的延迟。 pg_sleep_for
是一个便利函数,允许将休眠时间指定为 间隔
。 pg_sleep_until
是当需要特定唤醒时间时使用的一个便利函数。例如:
SELECT pg_sleep(1.5); SELECT pg_sleep_for('5 minutes'); SELECT pg_sleep_until('tomorrow 03:00');
休眠间隔的有效解析度取决于平台;0.01 秒是一个常见值。休眠延迟至少与指定的时间一样长。这可能会更长,具体取决于服务器负载等因素。具体而言,无法保证 pg_sleep_until
会在指定时间准时唤醒,但它不会提前唤醒。
调用 pg_sleep
或其变量时,请确保您的会话未保持太多锁。否则,其他会话可能不得不等待您休眠的进程,从而使整个系统变慢。