Table 9.31展示了可用于处理日期/时间值的函数,其细节在随后的小节中描述。Table 9.30演示了基本算术操作符 (+、*等)的行为。 而与格式化相关的函数,可以参考Section 9.8。你应该很熟悉Section 8.5中的日期/时间数据类型的背景知识。
此外, Table 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);我们只显示每一对中的一个。
Table 9.30. 日期/时间操作符
| 操作符 | 示例 | 结果 |
|---|---|---|
+ |
date '2001-09-28' + integer '7' |
date '2001-10-05' |
+ |
date '2001-09-28' + interval '1 hour' |
timestamp '2001-09-28 01:00:00' |
+ |
date '2001-09-28' + time '03:00' |
timestamp '2001-09-28 03:00:00' |
+ |
interval '1 day' + interval '1 hour' |
interval '1 day 01:00:00' |
+ |
timestamp '2001-09-28 01:00' + interval '23 hours' |
timestamp '2001-09-29 00:00:00' |
+ |
time '01:00' + interval '3 hours' |
time '04:00:00' |
- |
- interval '23 hours' |
interval '-23:00:00' |
- |
date '2001-10-01' - date '2001-09-28' |
integer '3'(天) |
- |
date '2001-10-01' - integer '7' |
date '2001-09-24' |
- |
date '2001-09-28' - interval '1 hour' |
timestamp '2001-09-27 23:00:00' |
- |
time '05:00' - time '03:00' |
interval '02:00:00' |
- |
time '05:00' - interval '2 hours' |
time '03:00:00' |
- |
timestamp '2001-09-28 23:00' - interval '23 hours' |
timestamp '2001-09-28 00:00:00' |
- |
interval '1 day' - interval '1 hour' |
interval '1 day -01:00:00' |
- |
timestamp '2001-09-29 03:00' - timestamp '2001-09-27 12:00' |
interval '1 day 15:00:00' |
* |
900 * interval '1 second' |
interval '00:15:00' |
* |
21 * interval '1 day' |
interval '21 days' |
* |
double precision '3.5' * interval '1 hour' |
interval '03:30:00' |
/ |
interval '1 hour' / double precision '1.5' |
interval '00:40:00' |
Table 9.31. 日期/时间函数
| 函数 | 返回类型 | 描述 | 示例 | 结果 |
|---|---|---|---|---|
|
interval |
减去参数,生成一个使用年和月,而不是只用日的“符号化”的结果 | age(timestamp '2001-04-10', timestamp '1957-06-13') |
43 years 9 mons 27 days |
|
interval |
从 current_date(午夜)减去 |
age(timestamp '1957-06-13') |
43 years 8 mons 3 days |
|
timestamp with time zone |
当前日期和时间(在语句执行期间变化);参见Section 9.9.4 | ||
|
date |
当前日期;参见 Section 9.9.4 | ||
|
time with time zone |
一天中的当前时刻;参见Section 9.9.4 | ||
|
timestamp with time zone |
当前日期和时间(当前事务开始时);参见Section 9.9.4 | ||
|
double precision |
获取子字段(等价于 extract);参见Section 9.9.1 |
date_part('hour', timestamp '2001-02-16 20:38:40') |
20 |
|
double precision |
获取子字段(等价于 extract);参见Section 9.9.1 |
date_part('month', interval '2 years 3 months') |
3 |
|
timestamp |
截断到指定的精度;参见 Section 9.9.2 | date_trunc('hour', timestamp '2001-02-16 20:38:40') |
2001-02-16 20:00:00 |
|
timestamp with time zone |
在规定的时区中截断到指定的精度;参见 Section 9.9.2 | date_trunc('day', timestamptz '2001-02-16 20:38:40+00', 'Australia/Sydney') |
2001-02-16 13:00:00+00 |
|
interval |
截断到指定的精度;参见 Section 9.9.2 | date_trunc('hour', interval '2 days 3 hours 40 minutes') |
2 days 03:00:00 |
|
double precision |
获取子字段;参见Section 9.9.1 | extract(hour from timestamp '2001-02-16 20:38:40') |
20 |
|
double precision |
获取子字段;参见Section 9.9.1 | extract(month from interval '2 years 3 months') |
3 |
|
boolean |
测试有限日期(不是+/-无限) | isfinite(date '2001-02-16') |
true |
|
boolean |
测试时间戳是否有限(不是正负无穷) | isfinite(timestamp '2001-02-16 21:28:30') |
true |
|
boolean |
测试时间间隔是否有限 | isfinite(interval '4 hours') |
true |
|
interval |
调整时间间隔,使 30 天的时段表示为月 | justify_days(interval '35 days') |
1 mon 5 days |
|
interval |
调整时间间隔,使 24 小时的时段表示为天 | justify_hours(interval '27 hours') |
1 day 03:00:00 |
|
interval |
使用 justify_days 和 justify_hours调整时间间隔; 通过额外的符号调整 |
justify_interval(interval '1 mon -1 hour') |
29 days 23:00:00 |
|
time |
一天中的当前时刻;参见Section 9.9.4 | ||
|
timestamp |
当前日期和时间(当前事务开始时);参见Section 9.9.4 | ||
|
date |
从年、月和日字段创建日期 | make_date(2013, 7, 15) |
2013-07-15 |
|
interval |
从年、月、周、日、小时、分钟和秒字段创建时间间隔 | make_interval(days => 10) |
10 days |
|
time |
从小时、分钟和秒字段创建时间 | make_time(8, 15, 23.5) |
08:15:23.5 |
|
timestamp |
从年、月、日、小时、分钟和秒字段创建时间戳 | make_timestamp(2013, 7, 15, 8, 15, 23.5) |
2013-07-15 08:15:23.5 |
|
timestamp with time zone |
从年、月、日、小时、分钟和秒字段创建带时区的时间戳;如果未指定 timezone,则使用当前时区。 |
make_timestamptz(2013, 7, 15, 8, 15, 23.5) |
2013-07-15 08:15:23.5+01 |
|
timestamp with time zone |
当前日期和时间(当前事务开始时);参见Section 9.9.4 | ||
|
timestamp with time zone |
当前日期和时间(当前语句的开始);参见 Section 9.9.4 | ||
|
text |
当前的日期和时间 (类似 clock_timestamp, 但是采用 text 字符串);参见 Section 9.9.4 |
||
|
timestamp with time zone |
当前日期和时间(当前事务开始时);参见Section 9.9.4 | ||
|
timestamp with time zone |
将 Unix 纪元时间(自 1970-01-01 00:00:00+00 起的秒数)转换为时间戳 | to_timestamp(1284352323) |
2010-09-13 04:32:03+00 |
(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');
结果:true
SELECT (DATE '2001-02-16', INTERVAL '100 days') OVERLAPS
(DATE '2001-10-30', DATE '2002-10-30');
结果:false
SELECT (DATE '2001-10-29', DATE '2001-10-30') OVERLAPS
(DATE '2001-10-30', DATE '2001-10-31');
结果:false
SELECT (DATE '2001-10-30', DATE '2001-10-30') OVERLAPS
(DATE '2001-10-30', DATE '2001-10-31');
结果:true
当把一个interval值加到某个时间戳上(或从该时间戳中减去一个interval值)时,如果该时间戳为timestamp with time zone类型,天数部分会相应增加或减少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'; 结果:2005-04-03 12:00:00-06SELECT timestamp with time zone '2005-04-02 12:00:00-07' + interval '24 hours'; 结果:2005-04-03 13:00:00-06
出现这种情况,是因为夏令时变化跳过了一个小时;变化发生的时间为2005-04-03 02:00:00,所在时区为America/Denver。
注意,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');
结果:10537200
SELECT (EXTRACT(EPOCH FROM timestamptz '2013-07-01 12:00:00') -
EXTRACT(EPOCH FROM timestamptz '2013-03-01 12:00:00'))
/ 60 / 60 / 24;
结果:121.958333333333
SELECT timestamptz '2013-07-01 12:00:00' - timestamptz '2013-03-01 12:00:00';
结果:121 days 23:00:00
SELECT age(timestamptz '2013-07-01 12:00:00', timestamptz '2013-03-01 12:00:00');
结果:4 mons
EXTRACT, date_part #EXTRACT(fieldFROMsource)
该extract函数从日期/时间值中提取年份、小时等子字段。source必须是以下类型的值表达式:timestamp, time,或interval。(date类型的表达式会转换为timestamp,因此也可以使用。)field是一个标识符或字符串,用于选择从源值中提取的字段。extract函数返回的值的类型为double precision。以下是有效的字段名称:
century世纪
SELECT EXTRACT(CENTURY FROM TIMESTAMP '2000-12-16 12:21:13'); 结果:20SELECT EXTRACT(CENTURY FROM TIMESTAMP '2001-02-16 20:38:40'); 结果: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'); 结果:16SELECT EXTRACT(DAY FROM INTERVAL '40 days 1 minute'); 结果:40
decade年份字段除以10
SELECT EXTRACT(DECADE FROM TIMESTAMP '2001-02-16 20:38:40');
结果:200
dow一周的日子从星期天(0)到星期六(6)
SELECT EXTRACT(DOW FROM TIMESTAMP '2001-02-16 20:38:40');
结果:5
请注意extract函数的星期几编号与to_char(..., 'D')函数不同。
doy一年中的第几天(1 - 365/366)
SELECT EXTRACT(DOY FROM TIMESTAMP '2001-02-16 20:38:40');
结果: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'); 结果:982384720.12SELECT EXTRACT(EPOCH FROM TIMESTAMP '2001-02-16 20:38:40.12'); 结果:982355920.12SELECT EXTRACT(EPOCH FROM INTERVAL '5 days 3 hours'); 结果:442800
您可以使用to_timestamp将一个 epoch 值转换回timestamp with time zone:
SELECT to_timestamp(982384720.12);
结果: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');
结果:20
isodow一周的日子从星期一(1)到星期日(7)
SELECT EXTRACT(ISODOW FROM TIMESTAMP '2001-02-18 20:38:40');
结果:7
这与dow相同,除了星期天。这匹配ISO 8601的星期几编号。
isoyear日期所属的 ISO 8601 周编号年份(不适用于间隔)
SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-01'); 结果:2005SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-02'); 结果:2006
每个 ISO 8601 周编号年都从包含 1 月 4 日的那一周的星期一开始,因此在 1 月初或 12 月末,ISO 年可能与格里高利年不同。更多信息请参见 week 字段。
PostgreSQL 8.3 之前的版本不支持此字段。
julian与日期或时间戳对应的儒略日(不适用于间隔)。非本地午夜的时间戳会产生带小数部分的值。更多信息请参见Section B.7。
SELECT EXTRACT(JULIAN FROM DATE '2006-01-01'); 结果:2453737SELECT EXTRACT(JULIAN FROM TIMESTAMP '2006-01-01 12:00'); 结果:2453737.5
microseconds秒字段,包括小数部分,乘以1 000 000;注意这包括完整的秒数
SELECT EXTRACT(MICROSECONDS FROM TIME '17:12:28.5');
结果:28500000
millennium千年
SELECT EXTRACT(MILLENNIUM FROM TIMESTAMP '2001-02-16 20:38:40');
结果:3
1900 年代的年份属于第二个千年。第三个千年始于 2001 年 1 月 1 日。
milliseconds第二个字段,包括小数部分,乘以1000。请注意,这包括完整的秒数。
SELECT EXTRACT(MILLISECONDS FROM TIME '17:12:28.5');
结果:28500
minute分钟字段(0 - 59)
SELECT EXTRACT(MINUTE FROM TIMESTAMP '2001-02-16 20:38:40');
结果:38
month对于 timestamp 值,表示一年中的月份编号(1 - 12);对于 interval 值,表示月数对 12 取模(0 - 11)
SELECT EXTRACT(MONTH FROM TIMESTAMP '2001-02-16 20:38:40'); 结果:2SELECT EXTRACT(MONTH FROM INTERVAL '2 years 3 months'); 结果:3SELECT EXTRACT(MONTH FROM INTERVAL '2 years 13 months'); 结果:1
quarter日期所在的一年中的季度(1 - 4)
SELECT EXTRACT(QUARTER FROM TIMESTAMP '2001-02-16 20:38:40');
结果:1
second秒字段,包括小数部分(0 - 59[7])
SELECT EXTRACT(SECOND FROM TIMESTAMP '2001-02-16 20:38:40'); 结果:40SELECT EXTRACT(SECOND FROM TIME '17:12:28.5'); 结果:28.5
timezone与UTC的时区偏移量,以秒为单位。正值对应于UTC东部的时区,负值对应于UTC西部的时区。 (从技术上讲,PostgreSQL不使用UTC,因为不处理闰秒。)
timezone_hour时间区偏移的小时组件
timezone_minute时间区偏移的分钟组件
week一年中ISO 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');
结果:7
year年份字段。请记住,没有0 AD,所以要小心地从AD年中减去BC年。
SELECT EXTRACT(YEAR FROM TIMESTAMP '2001-02-16 20:38:40');
结果:2001
当输入值为 +/-Infinity 时,extract对于单调增的域(epoch、julian、year、isoyear、decade、century以及millennium)返回 +/-Infinity。对于其他域返回 NULL。PostgreSQL 9.6 之前的版本对所有输入无穷的情况都返回零。
extract函数主要的用途是做计算性处理。对于用于显示的日期/时间值格式化,参阅Section 9.8。
该date_part函数仿照传统的Ingres实现,后者等价于SQL标准函数extract:
date_part('field', source)
注意,此处的field参数必须是字符串值,而不能是名称。函数date_part的有效字段名与以下函数相同:extract。
SELECT date_part('day', TIMESTAMP '2001-02-16 20:38:40');
结果:16
SELECT date_part('hour', INTERVAL '4 hours 3 minutes');
结果: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,其中所有小于所选精度的字段都设为零(日期和月份则设为一)。
field的有效值是∶
microseconds |
milliseconds |
second |
minute |
hour |
day |
week |
month |
quarter |
year |
decade |
century |
millennium |
当输入值的类型为timestamp with time zone时。截断是针对特定时区进行的。 例如,截断为day,产生的值是 是该区域的午夜。 默认情况下,截断是在以下方面进行的 到当前的TimeZone设置,但在当前的 可以提供可选的time_zone参数。以指定不同的时区。 可以指定时区名称 Section 8.5.3中描述的任何一种方式。
当处理timestamp without time zone 或interval输入时,不能指定时区。 这些总是按表面值来处理。
示例(假设本地时区为America/New_York):
SELECT date_trunc('hour', TIMESTAMP '2001-02-16 20:38:40');
结果:2001-02-16 20:00:00
SELECT date_trunc('year', TIMESTAMP '2001-02-16 20:38:40');
结果:2001-01-01 00:00:00
SELECT date_trunc('day', TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40+00');
结果:2001-02-16 00:00:00-05
SELECT date_trunc('day', TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40+00', 'Australia/Sydney');
结果:2001-02-16 08:00:00-05
SELECT date_trunc('hour', INTERVAL '3 days 02:47:33');
结果:3 days 02:00:00
AT TIME ZONE #AT TIME ZONE 可在不带时区和带时区的时间戳之间相互转换,也可将时间值转换到不同的时区。Table 9.32展示了它的各种变体。
Table 9.32. AT TIME ZONE 变体
| 表达式 | 返回类型 | 描述 |
|---|---|---|
|
timestamp with time zone |
将给定的不带时区时间戳视为指定时区中的时间 |
|
timestamp without time zone |
将给定的带时区时间戳转换为新时区的时间,结果不带时区标识 |
|
time with time zone |
将给定的带时区时间转换为新时区的时间 |
在这些表达式里,所需的时区 zone 可以指定为文本值(例如 'America/Los_Angeles'),也可以指定为一个间隔值(例如 INTERVAL '-08:00')。 在文本情况下,时区名称可以按 Section 8.5.3 中描述的任意方式指定。
示例(假设本地时区为America/Los_Angeles):
SELECT TIMESTAMP '2001-02-16 20:38:40' AT TIME ZONE 'America/Denver'; 结果:2001-02-16 19:38:40-08SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE 'America/Denver'; 结果:2001-02-16 18:38:40SELECT TIMESTAMP '2001-02-16 20:38:40-05' AT TIME ZONE 'Asia/Tokyo' AT TIME ZONE 'America/Chicago'; 结果:2001-02-16 05:38:40
第一个示例为不带时区的值添加时区,并使用当前TimeZone设置显示该值。第二个示例将带时区的时间戳值移到指定时区,并返回不带时区的值。这样就可以存储和显示与当前TimeZone设置不同的值。第三个示例将东京时间转换为芝加哥时间。将time值转换到其他时区时,由于没有提供日期,会使用当前生效的时区规则。
函数等效于 SQL 兼容的结构timezone(zone, timestamp)。timestamp AT TIME ZONE zone
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; 结果:14:39:53.662522-05SELECT CURRENT_DATE; 结果:2001-12-23SELECT CURRENT_TIMESTAMP; 结果:2001-12-23 14:39:53.662522-05SELECT CURRENT_TIMESTAMP(2); 结果:2001-12-23 14:39:53.66-05SELECT LOCALTIMESTAMP; 结果:2001-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, 这样需要默认值时就会得到创建表的时间!而前两种形式要到实际使用缺省值的时候才被计算, 因为它们是函数调用。因此它们可以给出每次插入行的时刻。 (参见 Section 8.5.1.4。)
以下函数可用于延迟服务器进程的执行:
pg_sleep(seconds) pg_sleep_for(interval) pg_sleep_until(timestamp with time zone)
pg_sleep使当前会话的进程休眠seconds秒。seconds的类型为double precision,因此可以指定带小数部分的秒数作为延迟时间。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或者其变体时,你的会话没有持有不必要 的锁。否则其它会话可能必须等待你的休眠会话,因而减慢整个系统速度。