Postgresql
將 varchar 列轉換為 inet
我有一個包含 IP 地址的表列,數據類型為
varchar(255)
. 我現在想切換到inet
數據類型。有沒有辦法將 IP 列中的現有地址轉換為inet
數據類型?試過:ALTER TABLE request_logs ALTER COLUMN ip type inet USING ip::inet; ALTER TABLE request_logs ALTER COLUMN ip type inet USING CAST(ip AS inet);
但沒有運氣,得到:
PG::DatatypeMismatch: ERROR: default for column "sign_up_ip" cannot be cast automatically to type inet
所有值都是
'127.0.0.1'
。Postgres 版本是 9.6.9。
該
ALTER TABLE
聲明對我有用。錯誤消息表明該列附加了sign_up_ip
一個**DEFAULT
**值,該值對新數據類型無效inet
。先去掉列的預設值,再轉換數據類型。然後添加一個新的預設值(如果適用)。即使它看起來是有效的。手冊,“更改列的數據類型”一章:
PostgreSQL 將嘗試將列的預設值(如果有)轉換為新類型,以及涉及該列的任何約束。但是這些轉換可能會失敗,或者可能會產生令人驚訝的結果。通常最好在更改其類型之前刪除列上的任何約束,然後再添加適當修改的約束。
varchar
和之間沒有註冊演員表inet
。這就是為什麼您必須添加USING
帶有顯式轉換的子句。Postgres 通過輸入/輸出轉換使其工作。DEFAULT
但這對於保存的表達式是不可能的。您可以在單個 DDL 命令中完成所有操作,以最大程度地減少與並發事務的摩擦(如果這很重要):
ALTER TABLE request_logs ALTER COLUMN sign_up_ip DROP default , ALTER COLUMN sign_up_ip type inet USING ip::inet , ALTER COLUMN sign_up_ip SET DEFAULT '192.168.1.1'; -- arbitrary example
使用您的實際列名
sign_up_ip
而不是程式碼範例中的符號ip
。在 Postgres 10 中測試。如果您的列應該包含任何
varchar
作為 type 無效的值inet
,那麼您的轉換仍然會失敗,但這次是這樣的:ERROR: invalid input syntax for type inet: "1234.123.123.123"
這就是為什麼在單個語句中(或至少在單個事務中)執行所有操作是一個好主意的原因之一:在錯誤和自動
ROLLBACK
.