表 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
將 interval
值加到(或從)timestamp
或 timestamp with time zone
值時,會依次處理 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
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
年ISO日期所屬的 ISO 8601 週編號年份
SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-01'); Result:2005
SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-02'); Result:2006
每個ISOISO 8601 週編號年份從包含 1 月 4 日的那一週的星期一開始,因此在一月初或十二月底,該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)
的編號ISOISO 8601 週編號年份的週數。 根據定義,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
年份 (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:00
SELECT EXTRACT(MINUTES FROM INTERVAL '80 minutes'); Result:20
當輸入值為 +/-Infinity 時,對於單調遞增的欄位,extract
傳回 +/-Infinity (epoch
、julian
、year
、isoyear
、decade
、century
和 millennium
用於 timestamp
輸入;epoch
、hour
、day
、year
、decade
、century
和 millennium
用於 interval
輸入)。 對於其他欄位,傳回 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
類型,並且它具有所有比所選值不重要的欄位都設定為零(或一天和一個月為一)。
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
放置到的 bin 的開頭。
範例
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 and 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
的簡寫,其中 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 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
或其變體時,請確保您的會話持有的鎖定不要超過必要的數量。否則,其他會話可能必須等待您的休眠程序,從而減慢整個系統的速度。
如果您在文件中發現任何不正確、與您使用特定功能的經驗不符或需要進一步澄清的地方,請使用此表單報告文件問題。