表 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 節
|
|
根據年、月、日欄位建立日期(負數年表示公元前)
|
|
根據年、月、周、日、小時、分鐘和秒欄位建立間隔,每個欄位都可以預設為零。
|
|
根據小時、分鐘和秒欄位建立時間
|
|
根據年、月、日、小時、分鐘和秒欄位建立時間戳(負數年表示公元前)
|
|
根據年、月、日、小時、分鐘和秒欄位建立帶時區的時間戳(負數年表示公元前)。如果未指定
|
|
當前日期和時間(當前事務的開始時間);參見第 9.9.5 節
|
|
當前日期和時間(當前語句的開始時間);參見第 9.9.5 節
|
|
當前日期和時間(類似於
|
|
當前日期和時間(當前事務的開始時間);參見第 9.9.5 節
|
|
將Unix紀元(自1970-01-01 00:00:00+00以來的秒數)轉換為帶時區的時間戳
|
(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
當向timestamp或timestamp with time zone值新增(或從中減去)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-06SELECT 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') 使用四月得到 1 mon 1 day,而使用五月會得到 1 mon 2 days,因為五月有31天,而四月只有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(fieldFROMsource)
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:20SELECT EXTRACT(CENTURY FROM TIMESTAMP '2001-02-16 20:38:40'); Result:21SELECT EXTRACT(CENTURY FROM DATE '0001-01-01 AD'); Result:1SELECT EXTRACT(CENTURY FROM DATE '0001-12-31 BC'); Result:-1SELECT EXTRACT(CENTURY FROM INTERVAL '2001 years'); Result:20
day月份中的日期(1-31);對於interval值,為天數
SELECT EXTRACT(DAY FROM TIMESTAMP '2001-02-16 20:38:40'); Result:16SELECT 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.120000SELECT EXTRACT(EPOCH FROM TIMESTAMP '2001-02-16 20:38:40.12'); Result:982355920.120000SELECT 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相同,除了星期日。這與ISO8601 星期幾編號相符。
isoyear該ISO日期所屬的 8601 周編號年份
SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-01'); Result:2005SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-02'); Result:2006
傳遞給 -c 的每個ISO8601 周編號年份從包含1月4日的星期一開始,因此在1月初或12月末,該ISO年份可能與公曆年份不同。有關更多資訊,請參閱week欄位。
julian與日期或時間戳對應的儒略日。非本地午夜的時間戳會導致分數。有關更多資訊,請參閱B.7 節。
SELECT EXTRACT(JULIAN FROM DATE '2006-01-01'); Result:2453737SELECT 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:3SELECT 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:2SELECT EXTRACT(MONTH FROM INTERVAL '2 years 3 months'); Result:3SELECT EXTRACT(MONTH FROM INTERVAL '2 years 13 months'); Result:1
quarter日期所在年份的季度(1-4);對於interval值,為月份欄位除以3加1
SELECT EXTRACT(QUARTER FROM TIMESTAMP '2001-02-16 20:38:40'); Result:1SELECT EXTRACT(QUARTER FROM INTERVAL '1 year 6 months'); Result:3
second秒欄位,包括任何小數秒
SELECT EXTRACT(SECOND FROM TIMESTAMP '2001-02-16 20:38:40'); Result:40.000000SELECT EXTRACT(SECOND FROM TIME '17:12:28.5'); Result:28.500000
timezoneUTC 的時區偏移量,以秒為單位。正值對應於 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 欄位一起使用以獲得一致的結果。
對於interval值,周欄位就是整數天數除以7。
SELECT EXTRACT(WEEK FROM TIMESTAMP '2001-02-16 20:38:40'); Result:7SELECT EXTRACT(WEEK FROM INTERVAL '13 days 24 hours'); Result:1
year年份欄位。請記住沒有0 AD,因此在從AD年份中減去BC年份時應謹慎。
SELECT EXTRACT(YEAR FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 2001
當處理interval值時,extract函式生成與間隔輸出函式使用的解釋相匹配的欄位值。如果從非規範化間隔表示開始,這可能會產生令人驚訝的結果,例如
SELECT INTERVAL '80 minutes'; Result:01:20:00SELECT EXTRACT(MINUTES FROM INTERVAL '80 minutes'); Result:20
當輸入值為 +/-Infinity 時,extract 對單調遞增的欄位(timestamp 輸入的epoch、julian、year、isoyear、decade、century和millennium;interval 輸入的epoch、hour、day、year、decade、century和millennium)返回 +/-Infinity。對於其他欄位,返回 NULL。PostgreSQL 9.6 之前的版本對於所有無限輸入情況都返回零。
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 型別,並且所有比所選欄位不重要的欄位都設定為零(或一,對於日和月)。
field 的有效值為
microseconds |
milliseconds |
second |
minute |
hour |
day |
week |
month |
quarter |
year |
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間隔必須大於零,並且不能包含月份或更大單位。
AT TIME ZONE 和 AT LOCAL #AT TIME ZONE 運算子將不帶時區的時間戳轉換為帶時區的時間戳,反之亦然,並將time with time zone值轉換為不同的時區。表 9.34 顯示了其變體。
表 9.34. AT TIME ZONE 和 AT LOCAL 變體
|
運算子 描述 示例 |
|---|
|
將給定的不帶時區的時間戳轉換為帶時區的時間戳,假設給定值在指定時區中。
|
|
將給定的不帶時區的時間戳轉換為帶會話
|
|
將給定的帶時區的時間戳轉換為不帶時區的時間戳,如同該時區中的時間一樣。
|
|
將給定的帶時區的時間戳轉換為不帶時區的時間戳,如同使用會話的
|
|
將給定的帶時區的時間轉換為新時區。由於未提供日期,因此使用指定目標時區的當前有效UTC偏移量進行轉換。
|
|
將給定帶時區的時間轉換為新的時區。由於未提供日期,因此使用會話 假設會話的
|
在這些表示式中,所需時區zone可以指定為文字值(例如,'America/Los_Angeles')或間隔(例如,INTERVAL '-08:00')。在文字情況下,時區名稱可以按第 8.5.3 節中描述的任何方式指定。間隔情況僅適用於與 UTC 具有固定偏移量的時區,因此在實踐中不常見。
語法AT LOCAL可以用作AT TIME ZONE 的簡寫,其中locallocal是會話的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-08SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE 'America/Denver'; Result:2001-02-16 18:38:40SELECT TIMESTAMP '2001-02-16 20:38:40' AT TIME ZONE 'Asia/Tokyo' AT TIME ZONE 'America/Chicago'; Result:2001-02-16 05:38:40SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT LOCAL; Result:2001-02-16 17:38:40SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE '+05'; Result:2001-02-16 20:38:40SELECT TIME WITH TIME ZONE '20:38:40-05' AT LOCAL; Result:17:38:40
第一個例子為缺少時區的值添加了一個時區,並使用當前TimeZone設定顯示該值。第二個例子將帶時區的時間戳值移到指定的時區,並返回不帶時區的值。這允許儲存和顯示不同於當前TimeZone設定的值。第三個例子將東京時間轉換為芝加哥時間。第四個例子將帶時區的時間戳值移到當前由TimeZone設定指定的時區,並返回不帶時區的值。第五個例子演示了POSIX風格時區規範中的符號與ISO-8601日期時間文字中的符號具有相反的含義,如第 8.5.3 節和附錄 B所述。
第六個例子是一個警示。由於輸入值沒有關聯日期,因此使用會話的當前日期進行轉換。因此,這個靜態示例可能會根據檢視的時間顯示錯誤的結果,因為'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-05SELECT CURRENT_DATE; Result:2019-12-23SELECT CURRENT_TIMESTAMP; Result:2019-12-23 14:39:53.662522-05SELECT CURRENT_TIMESTAMP(2); Result:2019-12-23 14:39:53.66-05SELECT 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 節。)
以下函式可用於延遲伺服器程序的執行:
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或其變體時,請確保您的會話持有的鎖不多於必要。否則,其他會話可能不得不等待您休眠的程序,從而減慢整個系統。
如果您在文件中發現任何不正確、與您使用特定功能的經驗不符或需要進一步澄清的內容,請使用此表格報告文件問題。