只要在搞資料,幾乎一定會遇到跟時間有關的東西。像是航班時刻表、訂單截止日,或是使用者什麼時候註冊網站,這些都跟時間脫不了關係。要處理這些東西,當然要有對的工具。PostgreSQL 就有專門的資料型別,超適合拿來存和處理日期、時間。
你當然可以直接把日期存成像 "2023-10-12" 這種普通字串,但這其實是個大坑。字串根本不會比日期大小、不知道什麼叫「加三天」,也完全不懂時區。可是時間型別就不一樣了,這些都難不倒它們。用起來又簡單又穩又快。
DATE 型別
DATE 型別就是專門拿來存「只有日期」的資料,不會記錄具體時間。像是生日、年度起始日這種只要日期就夠的情境超適合用。
範例:
-- 建立一個有 `DATE` 型別的資料表
CREATE TABLE events (
event_name TEXT,
event_date DATE
);
-- 插入資料
INSERT INTO events (event_name, event_date)
VALUES ('PostgreSQL 會議', '2023-12-01'),
('生日', '2023-10-12');
-- 查詢
SELECT * FROM events;
結果:
| event_name | event_date |
|---|---|
| PostgreSQL 會議 | 2023-12-01 |
| 生日 | 2023-10-12 |
TIME 型別
TIME 型別只存時間,也就是小時、分鐘、秒。像是公車時刻表、店家營業時段這種只要時間不用日期的情境就很適合。
範例:
-- 建立一個有 `TIME` 型別的資料表
CREATE TABLE schedules (
schedule_name TEXT,
start_time TIME,
end_time TIME
);
-- 插入資料
INSERT INTO schedules (schedule_name, start_time, end_time)
VALUES ('上班時間', '09:00:00', '18:00:00'),
('午餐休息', '13:00:00', '14:00:00');
-- 查詢
SELECT schedule_name, start_time, end_time FROM schedules;
結果:
| schedule_name | start_time | end_time |
|---|---|---|
| 上班時間 | 09:00:00 | 18:00:00 |
| 午餐休息 | 13:00:00 | 14:00:00 |
TIMESTAMP 型別
TIMESTAMP 型別會把日期和時間都存起來,但它不會記錄時區。如果你的資料會被不同時區的使用者用到,這就可能會搞混。
範例:
-- 建立一個有 `TIMESTAMP` 型別的資料表
CREATE TABLE documents (
document_id SERIAL PRIMARY KEY,
created_at TIMESTAMP
);
-- 插入資料
INSERT INTO documents (created_at)
VALUES ('2023-10-12 15:30:00'),
('2023-12-01 08:45:15');
-- 查詢
SELECT document_id, created_at FROM documents;
結果:
| document_id | created_at |
|---|---|
| 1 | 2023-10-12 15:30:00 |
| 2 | 2023-12-01 08:45:15 |
TIMESTAMPTZ 型別
TIMESTAMPTZ 型別(TZ 就是「時區」的意思)跟 TIMESTAMP 很像,但它還會記錄時區資訊。這對有國際用戶的應用來說超重要。
範例:
-- 建立一個有 `TIMESTAMPTZ` 型別的資料表
CREATE TABLE meetings (
meeting_id SERIAL PRIMARY KEY,
meeting_time TIMESTAMPTZ
);
-- 插入資料(PostgreSQL 會自動用目前的時區)
INSERT INTO meetings (meeting_time)
VALUES ('2023-10-12 15:30:00+03'),
('2023-12-01 08:45:15-05');
-- 查詢
SELECT meeting_id, meeting_time FROM meetings;
結果:
| meeting_id | meeting_time |
|---|---|
| 1 | 2023-10-12 15:30:00+03:00 |
| 2 | 2023-12-01 08:45:15-05:00 |
注意,PostgreSQL 會自動把時間轉成伺服器的時區。
用專門資料型別的好處
資料正確性。 像 DATE 跟 TIMESTAMP 這種型別可以防止你亂輸入。例如你不能存 "2023-02-30" 這種根本不存在的日期。
操作方便。 你可以直接比日期、做日期相減、拿到現在的日期,甚至還能做四捨五入(這個我們之後會講)。
效能好。 時間型別在記憶體和索引裡佔的空間比字串小,查詢速度也比較快。
範例:用所有型別建立一個表
我們來做一個複雜一點的活動時程表,會用到 DATE、TIME、TIMESTAMP 跟 TIMESTAMPTZ。
CREATE TABLE event_schedule (
event_id SERIAL PRIMARY KEY,
event_name TEXT NOT NULL,
event_date DATE NOT NULL,
start_time TIME NOT NULL,
end_time TIME NOT NULL,
full_start TIMESTAMP NOT NULL,
full_start_with_zone TIMESTAMPTZ NOT NULL
);
-- 插入資料
INSERT INTO event_schedule (
event_name, event_date, start_time, end_time, full_start, full_start_with_zone
)
VALUES
('早晨 meetup', '2023-11-10', '10:00:00', '11:30:00', '2023-11-10 10:00:00', '2023-11-10 10:00:00+03'),
('晚上 workshop', '2023-11-11', '18:00:00', '20:00:00', '2023-11-11 18:00:00', '2023-11-11 18:00:00+03');
-- 查詢
SELECT * FROM event_schedule;
結果:
| event_id | event_name | event_date | start_time | end_time | full_start | fullstartwith_zone |
|---|---|---|---|---|---|---|
| 1 | 早晨 meetup | 2023-11-10 | 10:00:00 | 11:30:00 | 2023-11-10 10:00:00 | 2023-11-10 10:00:00+03:00 |
| 2 | 晚上 workshop | 2023-11-11 | 18:00:00 | 20:00:00 | 2023-11-11 18:00:00 | 2023-11-11 18:00:00+03:00 |
這就是一個真的可以拿來管理時程的資料表。你可以看到不同的時間資料型別怎麼互補,根據需求選對的來用。
希望你現在都記得怎麼在 PostgreSQL 裡用 DATE、TIME、TIMESTAMP 跟 TIMESTAMPTZ 了。接下來的課我們會更深入玩時間函數,學怎麼用 SQL 查詢來抓、格式化、管理時間資料。
GO TO FULL VERSION