9.9. 日期/时间函数和运算符#
- 9.9.1.
EXTRACT
、date_part
- 9.9.2.
date_trunc
- 9.9.3.
date_bin
- 9.9.4.
AT TIME ZONE
- 9.9.5. 当前日期/时间
- 9.9.6. 延迟执行
表 9.33显示了日期/时间值处理的可用函数,详细信息显示在以下小节中。表 9.32说明了基本算术运算符 (+
、*
等) 的行为。有关格式化函数,请参阅第 9.8 节。您应该熟悉第 8.5 节中有关日期/时间数据类型的背景信息。
此外,表 9.1中显示的常用比较运算符可用于日期/时间类型。日期和时间戳(带或不带时区)都是可比较的,而时间(带或不带时区)和间隔只能与相同数据类型的其他值进行比较。将不带时区的 time 戳与带时区的 time 戳进行比较时,前者值被假定为由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
|
除了这些函数之外,还支持 SQLOVERLAPS
运算符
(start1, end1) OVERLAPS (start2, end2)
(start1, length1) OVERLAPS (start2, length2)
当两个时间段(由其端点定义)重叠时,此表达式返回真,不重叠时返回假。端点可以指定为日期、时间或时间戳对;或者作为日期、时间或时间戳,后跟一个间隔。当提供一对值时,可以先写开始或结束;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
当向timestamp
或timestamp with time zone
值添加interval
值(或从interval
值中减去interval
值)时,interval
值的月份、天数和微秒字段将依次处理。首先,一个非零月份字段将时间戳的日期按指示的月份数前进或后退,保持月份中的天数不变,除非它会超过新月份的结束,在这种情况下,将使用该月份的最后一天。(例如,3 月 31 日加 1 个月变为 4 月 30 日,但 3 月 31 日加 2 个月变为 5 月 31 日。)然后,天数字段将时间戳的日期按指示的天数前进或后退。在这两个步骤中,一天中的当地时间保持不变。最后,如果有一个非零微秒字段,则会逐字添加或减去它。在识别 DST 的时区中对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
9.9.1.EXTRACT
、date_part
#
EXTRACT(field FROM source)
extract
函数从日期/时间值中检索子字段,例如年份或小时。*source
必须是timestamp
、time
或interval
类型的值表达式。(date
类型的表达式会被强制转换为timestamp
,因此也可以使用。)field
*是一个标识符或字符串,用于选择从源值中提取哪个字段。extract
函数返回numeric
类型的值。以下字段名称有效
century
世纪
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
第一个世纪始于公元 0001-01-01 00:00:00,尽管他们当时并不知道。此定义适用于所有格里高利历国家/地区。没有世纪数 0,您从 -1 世纪到 1 世纪。如果您不同意这一点,请将您的投诉写给:教皇,罗马圣彼得大教堂,梵蒂冈。
day
对于
timestamp
值,日期(本月)字段 (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 起的秒数(该时间之前的 timestamp 为负值);对于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
将纪元值转换回timestamp with time zone
SELECT to_timestamp(982384720.12); Result:
2001-02-17 04:38:40.12+00
请注意,将
to_timestamp
应用于从date
或timestamp
值中提取的纪元可能会产生误导性结果:结果将有效地假定原始值已在 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
相同。这与 8601 星期几编号相匹配。isoyear
日期所在的 8601 周编号年(不适用于间隔)
SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-01'); Result:
2005
SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-02'); Result:2006
每个 8601 周编号年都从包含 1 月 4 日的星期一的星期开始,因此在 1 月初或 12 月末, 年可能与公历年不同。有关更多信息,请参见
week
字段。此字段在 8.3 之前的 PostgreSQL 版本中不可用。
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
千年
SELECT EXTRACT(MILLENNIUM FROM TIMESTAMP '2001-02-16 20:38:40'); Result:
3
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
对于
timestamp
值,年份中的月份数 (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
时区
以秒为单位衡量的 UTC 时区偏移量。正值对应于 UTC 以东的时区,负值对应于 UTC 以西的时区。(从技术上讲,PostgreSQL 不使用 UTC,因为不处理闰秒。)
timezone_hour
时区偏移量的小时部分
timezone_minute
时区偏移量的分钟部分
周
8601 年份的周数。根据定义,ISO 周从星期一开始,并且一年的第一周包含该年的 1 月 4 日。换句话说,一年的第一个星期四是该年的第 1 周。
在 ISO 周数系统中,1 月初的日期可能是上一年第 52 周或第 53 周的一部分,而 12 月末的日期可能是下一年的第一周的一部分。例如,
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 AD
,因此应谨慎地从AD
年中减去BC
年。SELECT EXTRACT(YEAR FROM TIMESTAMP '2001-02-16 20:38:40'); Result:
2001
注意
当输入值为 +/-Infinity 时,extract
会为单调递增字段(epoch
、julian
、year
、isoyear
、decade
、century
和millennium
)返回 +/-Infinity。对于其他字段,返回 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
9.9.2.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
,并且它具有所有小于所选字段的字段,设置为零(或对于日期和月份,设置为一)。
对于*field
*的有效值是
microseconds |
milliseconds |
second |
minute |
hour |
day |
周 |
month |
quarter |
年 |
decade |
century |
millennium |
当输入值类型为带时区的 timestamp
时,截断相对于特定时区执行;例如,截断到day
会生成该时区午夜的值。默认情况下,截断相对于当前时区设置执行,但可以提供可选*time_zone
*参数来指定不同的时区。时区名称可以用第 8.5.3 节中描述的任何方式指定。
处理不带时区的 timestamp
或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
9.9.3.date_bin
#
函数date_bin
将输入时间戳“分段”到指定间隔(步长)并与指定原点对齐。
date_bin(stride, source, origin)
*source
是类型为timestamp
或带时区的 timestamp
的值表达式。(类型为date
的值会自动转换为timestamp
。)stride
是类型为interval
的值表达式。返回值的类型同样为timestamp
或带时区的 timestamp
,并且它标记了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
*间隔必须大于零,并且不能包含月份或更大的单位。
9.9.4.AT TIME ZONE
#
AT TIME ZONE
运算符将不带时区的 time stamp 转换为带时区的 time stamp,并将带时区的 time
值转换为不同的时区。表 9.34显示了其变体。
表 9.34.AT TIME ZONE
变体
运算符 说明 示例 |
---|
将给定的 不带 时区的 time stamp 转换为 带 时区的 time stamp,假设给定值位于指定的时区。
|
将给定的 带 时区的 time stamp 转换为 不带 时区的 time stamp,因为时间将显示在该时区中。
|
将给定的 带 时区的 time 转换为新的时区。由于未提供日期,因此它对指定的目的地时区使用当前有效的 UTC 偏移。
|
在这些表达式中,所需的时区*zone
*可以指定为文本值(例如,'America/Los_Angeles'
)或间隔(例如,INTERVAL '-08:00'
)。在文本情况下,可以在第 8.5.3 节中描述的任何方式中指定时区名称。间隔情况仅适用于与 UTC 有固定偏移的时区,因此在实践中并不常见。
示例(假设当前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
第一个示例向缺乏时区的 value 添加时区,并使用当前TimeZone
设置显示 value。第二个示例将带时区的 time stamp 值移至指定的时区,并返回不带时区的 value。这允许存储和显示不同于当前TimeZone
设置的值。第三个示例将东京时间转换为芝加哥时间。
函数``timezone(*
zone*,*
timestamp*)
等同于符合 SQL 的结构*
timestamp*AT TIME ZONE*
zone*
。
9.9.5. 当前日期/时间#
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 with time zone
值。now()
是PostgreSQL中transaction_timestamp()
的传统等效项。
所有日期/时间数据类型还接受特殊文字值now
来指定当前日期和时间(同样,解释为事务开始时间)。因此,以下三个都返回相同的结果
SELECT CURRENT_TIMESTAMP;
SELECT now();
SELECT TIMESTAMP 'now'; -- but see tip below
提示
在指定稍后要评估的值时不要使用第三种形式,例如在表列的DEFAULT
子句中。系统会在解析常量时立即将now
转换为timestamp
,以便在需要默认值时使用表创建的时间!前两种形式在使用默认值之前不会进行评估,因为它们是函数调用。因此,它们将给出所需的默认行为,即默认为行插入时间。(另请参阅第 8.5.1.4 节。)
9.9.6. 延迟执行#
以下函数可用于延迟服务器进程的执行
pg_sleep ( double precision )
pg_sleep_for ( interval )
pg_sleep_until ( timestamp with time zone )
pg_sleep
使当前会话的进程休眠,直到给定的秒数过去。可以指定几分之一秒的延迟。pg_sleep_for
是一个方便的函数,允许将休眠时间指定为interval
。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
或其变体时,确保会话不持有比必要更多的锁。否则,其他会话可能必须等待正在休眠的进程,从而导致整个系统速度变慢。