Postgresql

將 varchar 列轉換為 inet

  • August 7, 2018

我有一個包含 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.

引用自:https://dba.stackexchange.com/questions/214169