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
式ではそれは不可能です。
すべてを1つの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
コード例では、記号ip
の代わりにactual列名sign_up_ip
を使用します。 Postgres 10でテスト済み。
If列に、タイプvarchar
として無効なinet
値を保持する必要がある場合でも、変換は失敗しますが、今回は次のようなもので:
ERROR: invalid input syntax for type inet: "1234.123.123.123"
これが、1つのステートメント(または少なくとも1つのトランザクション)ですべてを実行することが望ましい理由の1つです。エラーと自動ROLLBACK
の後ですべてが元の状態に戻ります。