CodeGym /課程 /SQL SELF /更改欄位的資料型別

更改欄位的資料型別

SQL SELF
等級 18 , 課堂 1
開放

想像一下,你又要幫大學建學生表格啦。又來了! :)

一開始你決定年齡欄位 age 用整數型別,設成 SMALLINT(適合 -32,768 到 32,767 的數字)。但過一陣子,資料庫越來越大,你還加了來自其他國家的學生,他們的年齡是...用天數算的!這時 SMALLINT 就不夠用了——該換成 INTEGER 之類的型別啦。

還有幾個常見的情境,會需要改資料型別:

  1. 數字範圍要變大或變小。
  2. 字串長度要調整(比如從 VARCHAR(50) 換成 VARCHAR(100))。
  3. 為了優化,換成別的資料型別(像把 TEXT 轉成 VARCHAR)。
  4. 一開始選錯型別(例如你填了 BOOLEAN,其實該用 INTEGER)。

更改資料型別的語法

在 PostgreSQL 裡,要改欄位的資料型別就是用 ALTER TABLE。這樣可以讓表格結構跟著需求變動。

ALTER TABLE table_name
ALTER COLUMN column_name TYPE new_data_type;

很簡單啦:指定表格名稱、要改的欄位,還有新型別就好。

範例 1:從 INTEGER 換成 BIGINT

假設我們有個學生表:

CREATE TABLE students (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    age INTEGER
);

一切都很順,直到年齡超過百萬歲(別問,純粹舉例啦!)。為了讓 PostgreSQL 不要崩潰,我們把 ageINTEGER 換成 BIGINT

ALTER TABLE students
ALTER COLUMN age TYPE BIGINT;

範例 2:增加字串長度

你建了一個課程表,課程名稱最多 50 個字:

CREATE TABLE courses (
    id SERIAL PRIMARY KEY,
    name VARCHAR(50)
);

結果發現課程名稱比你想像的還要長又複雜。這問題很好解決:

ALTER TABLE courses
ALTER COLUMN name TYPE VARCHAR(150);

範例 3:型別轉換

假設有個表,birth_date 欄位本來是文字:

CREATE TABLE employees (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100),
    birth_date TEXT
);

你發現用 TEXT 存日期很難查詢或排序。怎麼辦?把 TEXT 轉成 DATE

ALTER TABLE employees
ALTER COLUMN birth_date TYPE DATE USING birth_date::DATE;

注意 USING birth_date::DATE 這段。這是告訴 PostgreSQL 要先轉換資料再改型別。

為什麼有時候要明確轉換資料?

當 PostgreSQL 遇到型別變更時,會試著自動把現有資料轉成新型別。如果不行,就會報錯。比如把 TEXT 直接改成 INTEGER,沒說怎麼轉,肯定失敗。

問題範例

ALTER TABLE employees
ALTER COLUMN birth_date TYPE DATE;
-- 錯誤:無法將值 'not a date' 轉成 DATE 型別。

這問題有解。加上明確的轉換方式,用 USING

ALTER TABLE employees
ALTER COLUMN birth_date TYPE DATE USING to_date(birth_date, 'YYYY-MM-DD');

這裡我們用 to_date() 函數,把字串轉成日期格式。

USING 指令

在 PostgreSQL 裡,當你用 ALTER TABLE ... ALTER COLUMN ... TYPE 改型別時,有時候要 指定怎麼轉換現有資料——這時就要用 USING 關鍵字。

語法:

ALTER TABLE table_name
ALTER COLUMN column_name TYPE new_data_type
USING expression;

說明:

  • USING 讓你明確指定 從舊型別轉新型別的轉換公式
  • 這在 自動轉換不行或不明確 時特別有用。

簡單範例:字串 → 數字

ALTER TABLE users
ALTER COLUMN age TYPE INTEGER
USING age::INTEGER;

這裡 age 原本是 TEXT,我們要轉成 INTEGERUSING age::INTEGER 就是明確型別轉換。

範例:文字 → 日期

ALTER TABLE events
ALTER COLUMN event_date TYPE DATE
USING TO_DATE(event_date, 'YYYY-MM-DD');

如果 event_date 是像 '2023-10-25' 這樣的字串,我們就告訴 PostgreSQL 怎麼把它變成 DATE 型別

什麼時候 USING 必須要用?

  • 沒有直接型別轉換
  • 當資料需要 轉換格式
  • 當型別不相容(TEXTBOOLEANVARCHARINTEGER 等)。

更改資料型別時的常見錯誤

沒轉換資料就報錯。 如果資料不能自動轉成新型別,一定要用 USING 指定轉換方式。

ALTER TABLE employees
ALTER COLUMN birth_date TYPE DATE;
-- 錯誤:欄位 'birth_date' 有不合法的 DATE 型別值

操作會鎖住表格。 要注意,改資料型別時,表格會被鎖住不能寫入,直到操作完成。大表格尤其要小心,最好選流量低的時段操作。

跟其他表格和外鍵有關的問題。 如果欄位是外鍵的一部分,改型別會更麻煩。PostgreSQL 會要求你重建外鍵。

實用小撇步

一定要先檢查現有資料。 先用像 SELECT DISTINCT column_name 這種查詢,看看資料能不能順利轉型。

先測試再動手。 建個臨時表來練習,確定沒問題再改正式表。例如:

CREATE TEMP TABLE temp_students AS SELECT * FROM students;

別忘了 USING 當型別差很大時(像 TEXTNUMERIC),USING 就是你的救星。

現在你已經知道怎麼在 PostgreSQL 裡改欄位的資料型別啦。希望下次要調整資料結構時,你會很有信心。表格很聰明,但偶爾也要升級一下啦!

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