CodeGym /課程 /SQL SELF /處理時間和日期的資料型別: DATETIME

處理時間和日期的資料型別: DATETIMETIMESTAMPTIMESTAMPTZ

SQL SELF
等級 31 , 課堂 0
開放

只要在搞資料,幾乎一定會遇到跟時間有關的東西。像是航班時刻表、訂單截止日,或是使用者什麼時候註冊網站,這些都跟時間脫不了關係。要處理這些東西,當然要有對的工具。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 會自動把時間轉成伺服器的時區。

用專門資料型別的好處

資料正確性。DATETIMESTAMP 這種型別可以防止你亂輸入。例如你不能存 "2023-02-30" 這種根本不存在的日期。

操作方便。 你可以直接比日期、做日期相減、拿到現在的日期,甚至還能做四捨五入(這個我們之後會講)。

效能好。 時間型別在記憶體和索引裡佔的空間比字串小,查詢速度也比較快。

範例:用所有型別建立一個表

我們來做一個複雜一點的活動時程表,會用到 DATETIMETIMESTAMPTIMESTAMPTZ

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 裡用 DATETIMETIMESTAMPTIMESTAMPTZ 了。接下來的課我們會更深入玩時間函數,學怎麼用 SQL 查詢來抓、格式化、管理時間資料。

留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION