PostgreSQL 格式化函式提供了一組強大的工具,用於將各種資料類型(日期/時間、整數、浮點數、數值)轉換為格式化的字串,以及將格式化的字串轉換為特定的資料類型。 表 9.26 列出了這些函式。 這些函式都遵循一個通用的呼叫慣例:第一個引數是要格式化的值,第二個引數是定義輸出或輸入格式的模板。
表 9.26. 格式化函式
函式 描述 範例 |
---|
根據給定的格式將時間戳記轉換為字串。
|
根據給定的格式將時間間隔轉換為字串。
|
根據給定的格式將數字轉換為字串;適用於
|
根據給定的格式將字串轉換為日期。
|
根據給定的格式將字串轉換為數值。
|
根據給定的格式將字串轉換為時間戳記。(另請參閱表 9.33中的
|
to_timestamp
和 to_date
的存在是為了處理無法透過簡單轉換來轉換的輸入格式。 對於大多數標準日期/時間格式,只需將來源字串轉換為所需的資料類型即可,而且更容易。 同樣地,對於標準數值表示法,to_number
是不必要的。
在 to_char
輸出模板字串中,存在某些模式,這些模式會被識別並根據給定的值替換為適當格式化的資料。 任何不是模板模式的文字都會被簡單地逐字複製。 同樣地,在輸入模板字串(對於其他函式)中,模板模式識別要由輸入資料字串提供的數值。 如果模板字串中存在不是模板模式的字元,則輸入資料字串中的相應字元將被簡單地跳過(無論它們是否等於模板字串字元)。
表 9.27 顯示了可用於格式化日期和時間值的模板模式。
表 9.27. 日期/時間格式化的模板模式
模式 | 描述 |
---|---|
HH |
一天中的小時 (01–12) |
HH12 |
一天中的小時 (01–12) |
HH24 |
一天中的小時 (00–23) |
MI |
分鐘 (00–59) |
SS |
秒 (00–59) |
MS |
毫秒 (000–999) |
US |
微秒 (000000–999999) |
FF1 |
十分之一秒 (0–9) |
FF2 |
百分之一秒 (00–99) |
FF3 |
毫秒 (000–999) |
FF4 |
十分之一毫秒 (0000–9999) |
FF5 |
百分之一毫秒 (00000–99999) |
FF6 |
微秒 (000000–999999) |
SSSS , SSSSS |
午夜後的秒數 (0–86399) |
AM , am , PM 或 pm |
上午/下午指示符 (不含句點) |
A.M. , a.m. , P.M. 或 p.m. |
上午/下午指示符 (含句點) |
Y,YYY |
年份 (4 位或更多位數),含逗號 |
YYYY |
年份 (4 位或更多位數) |
YYY |
年份的最後 3 位數 |
YY |
年份的最後 2 位數 |
Y |
年份的最後 1 位數 |
IYYY |
ISO 8601 週編號年份 (4 位或更多位數) |
IYY |
ISO 8601 週編號年份的最後 3 位數 |
IY |
ISO 8601 週編號年份的最後 2 位數 |
I |
ISO 8601 週編號年份的最後 1 位數 |
BC , bc , AD 或 ad |
紀元指示符 (不含句點) |
B.C. , b.c. , A.D. 或 a.d. |
紀元指示符 (含句點) |
MONTH |
完整大寫月份名稱 (空白填補至 9 個字元) |
Month |
完整首字大寫月份名稱 (空白填補至 9 個字元) |
month |
完整小寫月份名稱 (空白填補至 9 個字元) |
MON |
縮寫大寫月份名稱 (英文為 3 個字元,本地化長度會有所不同) |
Mon |
縮寫首字大寫月份名稱 (英文為 3 個字元,本地化長度會有所不同) |
mon |
縮寫小寫月份名稱 (英文為 3 個字元,本地化長度會有所不同) |
MM |
月份數字 (01–12) |
DAY |
完整大寫日期名稱 (空白填補至 9 個字元) |
Day |
完整首字大寫日期名稱 (空白填補至 9 個字元) |
day |
完整小寫日期名稱 (空白填補至 9 個字元) |
DY |
縮寫大寫日期名稱 (英文為 3 個字元,本地化長度會有所不同) |
Dy |
縮寫首字大寫日期名稱 (英文為 3 個字元,本地化長度會有所不同) |
dy |
縮寫小寫日期名稱 (英文為 3 個字元,本地化長度會有所不同) |
DDD |
一年中的第幾天 (001–366) |
IDDD |
ISO 8601 週編號年份的第幾天 (001–371;一年中的第 1 天是第一個 ISO 週的星期一) |
DD |
月份中的第幾天 (01–31) |
D |
星期幾,星期日 (1 ) 到星期六 (7 ) |
ID |
ISO 8601 星期幾,星期一 (1 ) 到星期日 (7 ) |
W |
月份中的第幾週 (1–5) (第一週從該月的第一天開始) |
WW |
一年中的第幾週 (1–53) (第一週從該年的第一天開始) |
IW |
ISO 8601 週編號年份的第幾週 (01–53;一年中的第一個星期四是第 1 週) |
CC |
世紀 (2 位數字) (二十一世紀從 2001-01-01 開始) |
J |
儒略日 (自西元前 4714 年 11 月 24 日當地午夜以來的整數天數;請參閱第 B.7 節) |
Q |
季度 |
RM |
大寫羅馬數字月份 (I–XII;I=一月) |
rm |
小寫羅馬數字月份 (i–xii;i=一月) |
TZ |
大寫時區縮寫 |
tz |
小寫時區縮寫 |
TZH |
時區小時 |
TZM |
時區分鐘 |
OF |
與 UTC 的時區偏移量 (HH 或 HH : MM ) |
修飾符可以應用於任何範本模式,以改變其行為。例如,FMMonth
是具有 FM
修飾符的 Month
模式。表 9.28 顯示了日期/時間格式化的修飾符模式。
表 9.28. 日期/時間格式化的範本模式修飾符
修飾符 | 描述 | 範例 |
---|---|---|
FM 前綴 |
填滿模式 (抑制前導零和填補空格) | FMMonth |
TH 後綴 |
大寫序數後綴 | DDTH ,例如,12TH |
th 後綴 |
小寫序數後綴 | DDth ,例如,12th |
FX 前綴 |
固定格式全域選項 (請參閱使用說明) | FX Month DD Day |
TM 前綴 |
翻譯模式 (根據 lc_time 使用本地化的日期和月份名稱) | TMMonth |
SP 後綴 |
拼字模式 (尚未實作) | DDSP |
日期/時間格式化的使用說明
FM
抑制前導零和尾隨空格,否則會添加這些零和空格以使模式的輸出成為固定寬度。在 PostgreSQL 中,FM
僅修改下一個規範,而在 Oracle 中,FM
影響所有後續規範,並且重複的 FM
修飾符會切換填滿模式的開啟和關閉。
無論是否指定 FM
,TM
都會抑制尾隨空格。
to_timestamp
和 to_date
忽略輸入中的字母大小寫;因此,例如,MON
、Mon
和 mon
都接受相同的字串。當使用 TM
修飾符時,大小寫折疊會根據函數的輸入定序規則來完成 (請參閱 第 23.2 節)。
除非使用 FX
選項,否則 to_timestamp
和 to_date
會跳過輸入字串開頭和日期和時間值周圍的多個空格。例如,to_timestamp(' 2000 JUN', 'YYYY MON')
和 to_timestamp('2000 - JUN', 'YYYY-MON')
可以正常工作,但 to_timestamp('2000 JUN', 'FXYYYY MON')
會傳回錯誤,因為 to_timestamp
僅預期一個空格。FX
必須指定為範本中的第一個項目。
在 to_timestamp
和 to_date
的樣板字串中,分隔符號(空格或非字母/非數字字元)會比對輸入字串中的任何單一分隔符號,或被略過,除非使用 FX
選項。例如,to_timestamp('2000JUN', 'YYYY///MON')
和 to_timestamp('2000/JUN', 'YYYY MON')
可以運作,但 to_timestamp('2000//JUN', 'YYYY/MON')
會傳回錯誤,因為輸入字串中的分隔符號數量超過樣板中的分隔符號數量。
如果指定了 FX
,樣板字串中的分隔符號會完全比對輸入字串中的一個字元。但請注意,輸入字串字元不一定要與樣板字串中的分隔符號相同。例如,to_timestamp('2000/JUN', 'FXYYYY MON')
可以運作,但 to_timestamp('2000/JUN', 'FXYYYY MON')
會傳回錯誤,因為樣板字串中的第二個空格會佔用輸入字串中的字母 J
。
TZH
樣板模式可以比對帶正負號的數字。如果沒有 FX
選項,負號可能會不明確,並可能被解釋為分隔符號。此不明確性會以下列方式解決:如果樣板字串中 TZH
前面的分隔符號數量少於輸入字串中負號前面的分隔符號數量,則負號會被解釋為 TZH
的一部分。否則,負號會被視為值之間的分隔符號。例如,to_timestamp('2000 -10', 'YYYY TZH')
會將 -10
比對到 TZH
,但 to_timestamp('2000 -10', 'YYYY TZH')
會將 10
比對到 TZH
。
一般文字允許出現在 to_char
樣板中,並會逐字輸出。您可以將子字串放在雙引號中,強制將其解釋為文字,即使它包含樣板模式也是如此。例如,在 '"Hello Year "YYYY'
中,YYYY
會被年份資料取代,但 Year
中的單個 Y
則不會。在 to_date
、to_number
和 to_timestamp
中,文字和雙引號字串會導致跳過字串中包含的字元數;例如 "XX"
會跳過兩個輸入字元(無論它們是否為 XX
)。
在 PostgreSQL 12 之前,可以使用非字母或非數字字元跳過輸入字串中的任意文字。例如,to_timestamp('2000y6m1d', 'yyyy-MM-DD')
過去可以運作。現在您只能使用字母字元來達到此目的。例如,to_timestamp('2000y6m1d', 'yyyytMMtDDt')
和 to_timestamp('2000y6m1d', 'yyyy"y"MM"m"DD"d"')
會跳過 y
、m
和 d
。
如果您希望在輸出中包含雙引號,則必須在其前面加上反斜線,例如 '\"YYYY Month\"'
。反斜線在雙引號字串之外沒有其他特殊意義。在雙引號字串中,反斜線會使下一個字元被逐字採用,無論它是什麼(但除非下一個字元是雙引號或另一個反斜線,否則這沒有特殊效果)。
在 to_timestamp
和 to_date
中,如果年份格式規範少於四位數,例如 YYY
,並且提供的年份少於四位數,則年份將調整為最接近 2020 年的年份,例如,95
會變成 1995 年。
在 to_timestamp
和 to_date
中,負年份被視為表示西元前 (BC)。如果您同時寫入負年份和明確的 BC
欄位,您會再次得到西元 (AD)。輸入年份零被視為西元前 1 年。
在 to_timestamp
和 to_date
中,當處理超過 4 位數的年份時,YYYY
轉換有一個限制。您必須在 YYYY
之後使用一些非數字字元或樣板,否則年份始終會被解釋為 4 位數。例如(年份為 20000):to_date('200001130', 'YYYYMMDD')
將被解釋為 4 位數的年份;而是使用年份之後的非數字分隔符號,例如 to_date('20000-1130', 'YYYY-MMDD')
或 to_date('20000Nov30', 'YYYYMonDD')
。
在 to_timestamp
和 to_date
中,如果存在 YYY
、YYYY
或 Y,YYY
欄位,則會接受但忽略 CC
(世紀)欄位。如果 CC
與 YY
或 Y
一起使用,則結果會計算為指定世紀中的那一年。如果指定了世紀但未指定年份,則假定為該世紀的第一年。
在 to_timestamp
和 to_date
中,星期名稱或數字(DAY
、D
和相關欄位類型)會被接受,但在計算結果時會被忽略。對於季度 (Q
) 欄位也是如此。
在 to_timestamp
和 to_date
中,可以使用以下兩種方式之一指定 ISO 8601 週數日期(與格里曆日期不同)
年份、週數和星期幾:例如 to_date('2006-42-4', 'IYYY-IW-ID')
傳回日期 2006-10-19
。如果您省略星期幾,則假定為 1(星期一)。
年份和一年中的第幾天:例如 to_date('2006-291', 'IYYY-IDDD')
也會傳回 2006-10-19
。
嘗試使用 ISO 8601 週數欄位和格里曆日期欄位的混合來輸入日期是沒有意義的,並且會導致錯誤。在 ISO 8601 週數年份的上下文中,「「月份」」或「「月份中的日期」」的概念沒有意義。在格里曆年份的上下文中,ISO 週沒有意義。
雖然 to_date
會拒絕格里曆日期和 ISO 週數日期欄位的混合,但 to_char
不會,因為像 YYYY-MM-DD (IYYY-IDDD)
這樣的輸出格式規範可能很有用。但請避免寫入像 IYYY-MM-DD
這樣的程式碼;這會在年初附近產生令人意外的結果。(請參閱第 9.9.1 節,以取得更多資訊。)
在 to_timestamp
函數中,毫秒 (MS
) 或微秒 (US
) 欄位被用作小數點後的秒數。例如,to_timestamp('12.3', 'SS.MS')
並非 3 毫秒,而是 300 毫秒,因為轉換會將其視為 12 + 0.3 秒。因此,對於 SS.MS
格式,輸入值 12.3
、12.30
和 12.300
指定了相同的毫秒數。要得到三毫秒,必須寫成 12.003
,轉換會將其視為 12 + 0.003 = 12.003 秒。
這是一個更複雜的例子:to_timestamp('15:12:02.020.001230', 'HH24:MI:SS.MS.US')
是 15 小時、12 分鐘和 2 秒 + 20 毫秒 + 1230 微秒 = 2.021230 秒。
to_char(..., 'ID')
的星期幾編號與 extract(isodow from ...)
函數的編號相符,但 to_char(..., 'D')
的編號與 extract(dow from ...)
的星期幾編號不相符。
to_char(interval)
將 HH
和 HH12
格式化為 12 小時制時鐘上顯示的樣子,例如,零小時和 36 小時都輸出為 12
,而 HH24
輸出完整的小時值,在 interval
值中可能超過 23。
表 9.29 顯示了可用於格式化數值的樣板模式。
表 9.29. 數值格式化的樣板模式
模式 | 描述 |
---|---|
9 |
數位位置(若不重要則可省略) |
0 |
數位位置(即使不重要也不會省略) |
. (句點) |
小數點 |
, (逗號) |
群組(千位)分隔符 |
PR |
角括號中的負值 |
S |
錨定到數字的符號(使用 locale) |
L |
貨幣符號(使用 locale) |
D |
小數點(使用 locale) |
G |
群組分隔符(使用 locale) |
MI |
指定位置的減號(如果數字 < 0) |
PL |
指定位置的加號(如果數字 > 0) |
SG |
指定位置的加/減號 |
RN |
羅馬數字(輸入介於 1 和 3999 之間) |
TH 或 th |
序數後綴 |
V |
移動指定的數位數量(請參閱注意事項) |
EEEE |
科學記號表示法的指數 |
數值格式化的使用注意事項
0
指定一個始終會被印出的數位位置,即使它包含前導/尾隨零。9
也指定一個數位位置,但如果它是前導零,它將被一個空格替換,而如果它是尾隨零並且指定了填充模式,它將被刪除。(對於 to_number()
,這兩個模式字元是等效的。)
如果格式提供的有效位數少於要格式化的數字,to_char()
會將數字四捨五入到指定的有效位數。
模式字元 S
、L
、D
和 G
表示由目前 locale 定義的符號、貨幣符號、小數點和千位分隔符(請參閱 lc_monetary 和 lc_numeric)。模式字元句點和逗號表示那些確切的字元,具有小數點和千位分隔符的含義,而與 locale 無關。
如果在 to_char()
的模式中沒有明確規定符號,則會為符號保留一欄,並且它會錨定到(出現在數字的左側)。如果 S
出現在某些 9
的左側,它也會同樣錨定到數字。
使用 SG
、PL
或 MI
格式化的符號不會錨定到數字;例如,to_char(-12, 'MI9999')
產生 '- 12'
,但 to_char(-12, 'S9999')
產生 ' -12'
。(Oracle 實作不允許在 9
之前使用 MI
,而是要求 9
在 MI
之前。)
TH
不會轉換小於零的值,也不會轉換小數。
PL
、SG
和 TH
是 PostgreSQL 擴充功能。
在 to_number
中,如果使用非資料樣板模式(例如 L
或 TH
),則會跳過對應數量的輸入字元,無論它們是否符合樣板模式,除非它們是資料字元(也就是數字、符號、小數點或逗號)。例如,TH
會跳過兩個非資料字元。
帶有 to_char
的 V
將輸入值乘以 10^
,其中 n
n
是 V
後面的數位數量。帶有 to_number
的 V
以類似的方式除。 to_char
和 to_number
不支援將 V
與小數點結合使用(例如,不允許使用 99.9V99
)。
EEEE
(科學記號表示法)不能與任何其他格式化模式或修飾符組合使用,除了數字和小數點模式,並且必須位於格式字串的末尾(例如,9.99EEEE
是一個有效的模式)。
某些修飾符可以應用於任何樣板模式以更改其行為。例如,FM99.99
是帶有 FM
修飾符的 99.99
模式。 表 9.30 顯示了數值格式化的修飾符模式。
表 9.30. 數值格式化的樣板模式修飾符
修飾符 | 描述 | 範例 |
---|---|---|
FM 前綴 |
填充模式(抑制尾隨零和填充空白) | FM99.99 |
TH 後綴 |
大寫序數後綴 | 999TH |
th 後綴 |
小寫序數後綴 | 999th |
表 9.31 顯示了 to_char
函數的一些使用範例。
表 9.31. to_char
範例
運算式 | 結果 |
---|---|
to_char(current_timestamp, 'Day, DD HH12:MI:SS') |
'Tuesday , 06 05:39:18' |
to_char(current_timestamp, 'FMDay, FMDD HH12:MI:SS') |
'Tuesday, 6 05:39:18' |
to_char(current_timestamp AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS"Z"') |
'2022-12-06T05:39:18Z' , ISO8601 擴充格式 |
to_char(-0.1, '99.99') |
' -.10' |
to_char(-0.1, 'FM9.99') |
'-.1' |
to_char(-0.1, 'FM90.99') |
'-0.1' |
to_char(0.1, '0.9') |
' 0.1' |
to_char(12, '9990999.9') |
' 0012.0' |
to_char(12, 'FM9990999.9') |
'0012.' |
to_char(485, '999') |
' 485' |
to_char(-485, '999') |
'-485' |
to_char(485, '9 9 9') |
' 4 8 5' |
to_char(1485, '9,999') |
' 1,485' |
to_char(1485, '9G999') |
' 1 485' |
to_char(148.5, '999.999') |
' 148.500' |
to_char(148.5, 'FM999.999') |
'148.5' |
to_char(148.5, 'FM999.990') |
'148.500' |
to_char(148.5, '999D999') |
' 148,500' |
to_char(3148.5, '9G999D999') |
' 3 148,500' |
to_char(-485, '999S') |
'485-' |
to_char(-485, '999MI') |
'485-' |
to_char(485, '999MI') |
'485 ' |
to_char(485, 'FM999MI') |
'485' |
to_char(485, 'PL999') |
'+485' |
to_char(485, 'SG999') |
'+485' |
to_char(-485, 'SG999') |
'-485' |
to_char(-485, '9SG99') |
'4-85' |
to_char(-485, '999PR') |
'<485>' |
to_char(485, 'L999') |
'DM 485' |
to_char(485, 'RN') |
' CDLXXXV' |
to_char(485, 'FMRN') |
'CDLXXXV' |
to_char(5.2, 'FMRN') |
'V' |
to_char(482, '999th') |
' 482nd' |
to_char(485, '"Good number:"999') |
'Good number: 485' |
to_char(485.8, '"Pre:"999" Post:" .999') |
'Pre: 485 Post: .800' |
to_char(12, '99V999') |
' 12000' |
to_char(12.4, '99V999') |
' 12400' |
to_char(12.45, '99V9') |
' 125' |
to_char(0.0004859, '9.99EEEE') |
' 4.86e-04' |
如果您在文件中發現任何不正確、與特定功能的使用經驗不符或需要進一步說明之處,請使用此表格來回報文件問題。