Webエンジニアの森脇です。 PostgreSQLで、サービス稼働中に安易にALTER TABLE等を実行すると、ダウンタイムに繋がることがあります。安全にテーブル定義を変更するために、弊社で気をつけている点を紹介します。 なお、本記事の内容は PostgreSQL 9.5.4 環境で確認しています。 パラメータによりますが、予定の効果を得るためにテーブルを書き換える必要がある場合があります。 制約用のトリガを有効または無効にするにはスーパーユーザ権限が必要です。 テーブルの作成後に間違いに気付いたり、あるいはアプリケーションの要件が変わったりした場合には、テーブルをいったんドロップして再度作成することができます。 この場合は、DROP DEFAULTでデフォルト値を削除し、ALTER TYPEを実行した後で、SET DEFAULTを使用して再度適切なデフォルト値を指定してください。 しかし、もし列が他のテーブルの外部キー制約として参照されている場合は、PostgreSQLは暗黙のうちに制約を消去しません。 EXTENDEDは、PLAIN以外の保管をサポートするほとんどのデータ型におけるデフォルトです。 遅延トリガの場合、有効無効状態の確認は、トリガ関数を実際に実行しようとする時ではなく、イベントの発生時に行われます。 ALTER TABLE distributors ADD COLUMN address varchar(30); テーブルから列を削除します。 ALTER TABLE distributors DROP COLUMN address RESTRICT; 1つの操作で既存の2つの列の型を変更します。 ALTER TABLE distributors ALTER COLUMN address TYPE varchar(80), ALTER … 古いデータ型から新しいデータ型への暗黙キャストあるいは代入キャストがない場合、USING句を指定しなければなりません。, これらの構文を使用すると、列のデフォルト値を設定または削除できます。 つまり、常にONLYが指定されているかのように動作します。 ALTER TABLEは既存のテーブルの定義を変更します。 ALTER TABLE employee MODIFY empno NULL カラムの桁数を変更する. しかし、テーブルにデータを入力済みの場合、あるいはそのテーブルが他のデータベースオブジェクト (例えば外部キー制約)によって参照されている場合、これは良い方法ではありません。 alter table テーブル名 alter column 変更する列名 データ型 例:alter table table_a alter column column_1 varchar(200) ・表の列を削除する. このコマンドによってテーブルの内容が即座に変更されない点に注意してください。 ALTER TABLE distributors ADD COLUMN address varchar(30); テーブルから列を削除します。 ALTER TABLE distributors DROP COLUMN address RESTRICT; 1つの操作で既存の2つの列の型を変更します。 ALTER TABLE distributors ALTER COLUMN address TYPE varchar(80), ALTER … Oracleなどでは ``` ALTER TABLE テーブル名 MODIFY カラム名 データ型 ``` でカラムのデータ型の変更を行えますが、 PostgreSQLではMODIFYを使っても変更できません。 PostgreSQLでカラムのデータ型を変更する場合は以下のようなSQL文を実行します。 ``` ALTER TABLE テーブル名 ALTER COLUMN カラム名 TYPE データ型 ```, ALTER TABLE products ALTER COLUMN price SET DEFAULT 7.77; デフォルト値を削除するには常に次のようにします。 ALTER TABLE products ALTER COLUMN price DROP DEFAULT; これはデフォルトを NULL に設定することと同等です (少なくとも PostgreSQL では)。 PostgreSQL 8.x 当初の想定より長い文字列を格納することになったのでサイズを大きくするなど。 ALTER TABLE video ALTER COLUMN title TYPE VARCHAR(1024); 変更後のサイズを超えるデータが格納されていたらエラーになる。 alter table [テーブル名] alter column [カラム名] set not null; 設計の最初の段階で全ての項目がどうあるべきってなかなか把握しきれないので、後から変更することはよくあります。そんな時によくやるオペレーションなので覚えていると便利です。 alter table ir_calendar alter text_col type character(256); としたところ、エラーになる。 なんと、動いているPostgreSQLのバージョンが、7.4であった。このSQLは8.0でないと動かない。 ALTER TABLE distributors ADD COLUMN address varchar(30); テーブルから列を削除します。 ALTER TABLE distributors DROP COLUMN address RESTRICT; 1つの操作で既存の2つの列の型を変更します。 ALTER TABLE distributors ALTER COLUMN address TYPE varchar(80), ALTER …, ALTER TABLEで列の桁数を変更できる。列の桁数を縮小する場合、既存データの最大桁数より小さくすることはできない。 ALTER TABLE emp MODIFY (ename VARCHAR2(100)) テーブルからカラムを削除する. 対象を-1に設定すると、システムのデフォルト統計情報対象(default_statistics_target)が使用されます。 指定したデフォルト値は、変更後に行われるINSERTコマンドのみに適用されます。 この領域は、その後既存の行が更新されるタイミングで回収されます。, ALTER TYPEがテーブル全体の書き換えを必要とすることが利点になる場合もあります。 また、ユーザトリガのみを指定することも可能です(このオプションは外部キー制約を実装するために使用されるトリガを除外します)。 SET STORAGE自体はテーブルをまったく変更しないことに注意してください。 ALTER TABLEで列の桁数を変更できる。列の桁数を縮小する場合、既存データの最大桁数より小さくすることはできない。 ALTER TABLE emp MODIFY (ename VARCHAR2(100)) テーブルからカラムを削除する 実際のテーブルの再クラスタ化は行いません。, この構文は、テーブルから、一番最後に適用されたCLUSTERインデックス指定を削除します。 テーブルが巨大な場合、この処理に非常に時間がかかる可能性があります。また、一時的に2倍のディスク容量が必要とされます。, CHECKあるいはNOT NULL制約を追加する時は、既存の行が制約に従うかどうかを検証するためにテーブルの走査が必要になります。, 単一のALTER TABLE内に複数の変更を指定できるオプションを提供する主な理由は、複数のテーブル走査や書き換えを1回のテーブル走査にまとめることができるようにすることです。, DROP COLUMN構文は、列を物理的には削除せず、SQLを操作する上で不可視にします。 ONLYが指定された場合、そのテーブルのみが変更されます。 また列を含むテーブルの制約も消去されます。 トリガが実行されなかった場合に当然ながら制約の整合性が保証されませんので、注意して実行しなければなりません。, この構文は、以後のCLUSTER操作用のデフォルトインデックスを選択します。 より複雑な変換が必要な場合、古い値から新しい値をどのように計算するかを指定するUSING句を付けることができます。, PostgreSQLは、(もしあれば)列のデフォルト値を新しい型に、同時に、その列に関連する全ての制約も新しい型に変換しようとします。 Postgresql-varcharカラムのサイズを変更する (6) . また、所有者を変更するには、新しい所有ロールの直接あるいは間接的なメンバでなければならず、かつ、そのロールがテーブルのスキーマにおけるCREATE権限を持たなければなりません 親テーブルへの問い合わせでは、対象としたテーブルからのデータが含まれなくなります。, この形式を使用すると、テーブル、シーケンス、またはビューの所有者を、指定したユーザに変更できます。, この構文を使用すると、テーブルのテーブル空間を指定したテーブル空間に変更し、テーブルに関連するデータファイルを新しいテーブル空間に移動することができます。 設定可能なパラメータに関してはCREATE TABLEを参照してください。 格納されているデータへの影響はありません。, この構文を使用して、テーブルを別のスキーマに移動することができます。 また、単一のALTER TABLEコマンド内に複数の操作を指定する機能もPostgreSQLの拡張です。, ALTER TABLE DROP COLUMNを使って、1つしか列がないテーブルから列を削除して、列がないテーブルを作成することができます。 しかし、自分で名前を付けていない場合はシステム生成の名前が割り当てられているので、それを探さなくてはなりません。 テーブルのスキーマを変更するには、新しいスキーマにおけるCREATE権限も持たなければなりません。 列のデータ型の変更. ALTER TABLE distributors DROP COLUMN address RESTRICT; 1つの操作で既存の2つの列の型を変更します。 ALTER TABLE distributors ALTER COLUMN address TYPE varchar(80), ALTER … ALTER TABLEで列の桁数を変更できる。列の桁数を縮小する場合、既存データの最大桁数より小さくすることはできな … しかし、自分で名前を付けていない場合はシステム生成の名前が割り当てられているので、それを探さなくてはなりません。 この柔軟性のため、USING式は列のデフォルト値には(仮に存在していても)適用されません。 型を変更する前にその列に関する制約を全て削除し、後で適切に変更した制約を付け直すことが最善な場合がよくあります。. そのため、定義されていないデフォルト値を削除してもエラーにはなりません。 ONLYが指定されていない場合、そのテーブルおよび(存在する場合は)そのテーブルを継承する全てのテーブルが更新されます。 PostgreSQLの問い合わせプランナによる統計情報の使用に関する詳細は、項13.2を参照してください。, この構文は、列の保管モードを設定します。 しかし、デフォルトが指定されていない場合は、PostgreSQLは物理的な更新を避けることが可能です。 他の構文は標準SQLに対するPostgreSQLの拡張です。 結果が定数式にならない可能性があるためです(デフォルト値は定数式でなければいけません)。 CASCADEを追加することにより列に依存する全てを消去することができます。, テーブル制約として記述できない非NULL制約を追加するには、次の構文を使用します。, 制約は即座に検査されますので、制約を追加する前にテーブル内のデータがこれに従っている必要があります。, 制約を削除するには、その制約名を知る必要があります。 親テーブルに新しい子テーブルを追加するには、親テーブルも同様に所有している必要があります。 これらの列のデータ型は一致している必要があり、親テーブルでNOT NULL制約がある場合は、子テーブルでも同様にNOT NULL制約を持たなければなりません。, また、親テーブルのCHECK制約すべてについても、一致する制約が子テーブルに存在しなければなりません。 そのため、一般的な変換をALTER TYPE構文で行うことができます。 SET NOT NULLは、その列にNULL値が1つもない場合にのみ設定可能です。, この構文は、コマンド実行後に行なわれるANALYZE操作において、列単位での統計情報収集対象を設定します。 このためには、テーブルを強制的に書き換えるCLUSTERまたはALTER TABLEの構文のいずれかを使用してください。, 注意: CREATE TABLEではOIDSをWITH (storage_parameter)構文で指定することができますが、ALTER TABLEではOIDSを格納パラメータとして扱っていません。, この構文は、1つ以上の格納パラメターをデフォルト値に再設定します。 ALTER TABLE テーブル名 RENAME 現在のカラム名 TO 変更後のカラム名; 以下の例は、テーブル「access」の、カラム「addr」を、「ipaddr」に変更します。 ALTER TABLE access RENAME addr TO ipaddr; カラムのデータ型の変更 ALTER TABLE test_table ALTER column_name TYPE varchar(32); 省略された場合、デフォルトの変換は、古いデータ型から新しいデータ型への代入キャストと同じになります。 また、削除する列にテーブル以外(例えば、外部キー制約、ビューなど)が依存している場合、CASCADEを付ける必要があります。, この構文を使用すると、テーブルの列の型を変更できます。 これは特に巨大なテーブルでは便利です。変更のために必要なテーブル全体の走査が1回で済むからです。, ALTER TABLEコマンドを使用するには、変更するテーブルを所有している必要があります。 EXTERNALを使用すると、textおよびbytea列に対する部分文字列操作の処理速度が向上しますが、必要な保管容量が増えるというデメリットがあります。 列のデータ型の変更. このコマンドには、次のような副構文があります。, この構文を使用すると、CREATE TABLEと同じ構文を使って新しい列をテーブルに追加できます。, この構文を使用すると、テーブルから列を削除できます。 インデックスを移動するには、別途SET TABLESPACEコマンドを実行します。 削除する代わりに、その列は継承されておらず独立して定義されているという印を付けます。, TRIGGER、CLUSTER、OWNERおよびTABLESPACEは子テーブルに再帰的に伝わりません。 詳細は項52.2を参照してください。, この構文を使用すると、CREATE TABLEと同じ構文を使って新しい制約をテーブルに追加できます。, この構文を使用すると、テーブルに属するトリガを無効または有効にすることができます。 Postgresql-varcharカラムのサイズを変更する (6) Greg Smith によって記述されたページのキャッシュがあります。 死んだ場合でも、alter文は次のようになります。 ... ALTER TABLE mytable ALTER COLUMN mycolumn TYPE varchar(40); 関連するインデックスや制約、テーブル列により所有されるシーケンスも同様に移動されます。, RENAMEおよびSET SCHEMA以外の全ての操作は、結合して複数の変更リストにまとめて、並行に処理することができます。 第5章に、継承に関するさらに詳しい情報があります。, USING句を使用して、Unixタイムスタンプを持つinteger型の列をtimestamp with time zoneに変更します。, 上と同じです。 その列を含むインデックスと簡単なテーブル制約は、元々与えられた式を再解析し、新しい型を使用するように自動的に変換されます。 デフォルト値はビューに対して設定することも可能です。 コマンドは以下の通りです。, (自動生成された$2といった制約名を扱う場合は、有効な識別子となるように二重引用符で括る必要があることを忘れないでください。), 列の削除に関して、何かが依存している制約を削除する場合にはCASCADEを付ける必要があります。例として、参照されている列に付いている一意またはプライマリキー制約に依存している外部キー制約を削除する場合です。, これは、非NULL制約以外の全ての制約型に適用できます。 テーブル名に *を付けると継承テーブルが変更されることを明示できますが、現在のバージョンでは、継承テーブルの変更はデフォルトで行われます ここでは、テーブルの定義や構造を変更することに焦点を当てます。, 新しい列にはデフォルト値が初期値として入ります(DEFAULT句を指定しない場合はNULL値が入ります)。, 実際にはCREATE TABLE内の列の記述に使用されている全てのオプションが、ここで使用できます。 この場合、ビューのON INSERTルールが適用される前に、ビューのINSERT文にデフォルトが挿入されます。, これらの構文は、列の値としてNULL値を使用できるかどうか設定します。 ここでは、テーブルの定義や構造を変更することに焦点を合わせます。, これらの操作は全てALTER TABLEコマンド(本節の説明範囲を超えますので詳細はこちらを参照してください)を使用して行うことができます。, 新しい列にはデフォルト値が初期値として入ります(DEFAULT句を指定しない場合はNULL値が入ります)。, 実際にはCREATE TABLE内の列の記述に使用されている全てのオプションが、ここで使用できます。 テーブルにインデックスがあっても移動されません。 primary keyの追加はALTER TABLE文を使用します。primary keyに設定するカラムにはNOT NULL制約が設定されている必要があります。, ALTER TABLE employee MODIFY empno NULL カラムの桁数を変更する. このコマンドを実行した後、テーブルに挿入または更新が行われると、削除した列にはNULLが格納されます。 ただし、その列は、自動的に新しいデータ型にキャストされないデフォルト式を持ちます。, 自動的に命名されるプライマリキー制約をテーブルに付与します。 SET同様、テーブル全体を更新するためにテーブルの書き換えが必要になる場合があります。, この構文は、対象テーブルを指定した親テーブルの子テーブルとして追加します。 テーブルの作成後に間違いに気付いたり、あるいはアプリケーションの要件が変わったりした場合には、テーブルをいったんドロップして再度作成することができます。 しかし、テーブルにデータを入力済みの場合、あるいはそのテーブルが他のデータベースオブジェクト(例えば外部キー制約)によって参照されている場合、これは良い方法ではありません。 名前でトリガを1つ指定して有効または無効にすることもできますし、テーブル上のすべてのトリガを指定することもできます。 その後に、後述のようにして設定したいデフォルト値を付与してください。, 列内にある、どんなデータであれ消去します。 USING句は、古い列値をどのように新しい値に計算するかを指定します。この句は省略可能です。 ですので、ほとんどがデフォルト以外の値を持つ列をテーブルに格納するつもりであれば、デフォルトを指定せずに列を追加し、UPDATEを使用して正しい値を挿入することをお勧めします。 再帰的でないDROP COLUMN(例えば、ALTER TABLE ONLY ... DROP COLUMNなど)操作では、継承された列は削除されません。 既にoid列が存在しなくても警告が表示されない点を除けば、DROP COLUMN oid RESTRICTとまったく同等です。, OIDを削除後、再度テーブルにOIDを保存するよう指定するALTER TABLEの副構文は存在しないことに注意してください。, この構文は、1つ以上のテーブルの格納パラメータを変更します。 そのため、定義されていないデフォルト値を削除してもエラーにはなりません。 自分で名前を付けた場合は簡単です。 非NULL制約をドロップするには、次のようにします。, これはテーブル内の既存の行には何も影響を与えないことに注意してください。これは将来のINSERTコマンドのために単純にデフォルトを変えるだけです。, これは、デフォルトをNULLに設定することと同等です。 alter table testm add newdata1 int8 ; ・PostgreSQL では、列名の変更ができる。 alter table testm rename data1 to abc ; ・PostgreSQL では、列の項目タイプ定義変更はできないようである。 項目タイプを変更するためには、テーブルを作り直すしかない。 また列を含むテーブルの制約も消去されます。 列を異なるデータ型に変換するには以下のようなコマンドを使用してください。 ALTER TABLE products ALTER COLUMN price TYPE numeric(10,2); これは、その列の既存の項目が新しい型に暗黙的キャストにより変換できる場合にのみ成功します。 列をインラインで保持するか補足テーブルに保持するか、また、データを圧縮するかどうかを制御できます。 現時点ではUNIQUE、PRIMARY KEY、FOREIGN KEY制約は無視されますが、将来変更されるかもしれません。, この構文は、指定した親テーブルから子テーブル群を削除します。 EXTENDEDは圧縮された外部データに使用します。 列を異なるデータ型に変換するには以下のようなコマンドを使用してください。 ALTER TABLE products ALTER COLUMN price TYPE numeric(10,2); これは、その列の既存の項目が新しい型に暗黙的キャストにより変換できる場合にのみ成功します。 他のインタフェースにもテーブルの詳細を調べる方法があるかもしれません。 ただしデフォルト値は与えられている制約を満足するものでなくてはいけないことに注意してください。満足しない場合はADDが失敗します。一方で、新規の列に正しく値を入れた後で制約を追加することができます(後述されています)。, 列内にある、どんなデータであれ消去します。 テーブル内の既存の行は変更されません。 その後に行われる親テーブルへの問い合わせには対象テーブルの項目も含まれます。 型を変更する前にその列に関する制約を全て削除し、後で適切に変更した制約を付け直すことが最善な場合がよくあります。. これがデフォルトの動作です。, テーブルに属するすべてのトリガを有効または無効にします。 しかし、こうした変換は失敗するかもしれませんし、予想を超えた結果になってしまうかもしれません。 Oracleのテーブルの列の桁数を変更するMODIFY【SQL】Oracleのテーブルは作成後でもテーブルの列の桁数をSQLで変更できます。テーブルの列の桁数を変更するSQLは、ALTER TABLE~MODIFY~を使いま … 私は本当に大きなテーブル(約30百万行)のALTER TABLEコマンドに関する質問があります。その列の1つはvarchar(255) varchar(40)です。これをvarchar(40)にサイズ変更したいと思います。 CREATE TABLESPACEも参照してください。, RENAME構文を使用すると、テーブル(もしくは、インデックス、シーケンス、ビュー)の名前や、テーブルの個々の列名を変更できます。 5.6.6. そのため、PostgreSQL では既存のテーブルに変更を加えるための一連のコマンドが用意されています。テーブル内のデータを変更するという概念ではないことに注意してください。 しかし、削除された列が占めていた領域がまだ回収されていないため、テーブルのディスク上のサイズはすぐには小さくなりません。 なぜなら NULL値が暗黙的にデフォルトとなっているからです。, これは、その列の既存の項目が新しい型に暗黙的キャストにより変換できる場合にのみ成功します。 制約の追加は、CHECK制約に関してのみ再帰的に伝わります。, 有効なパラメータの詳しい説明はCREATE TABLEを参照してください。 ALTER TABLEで列の桁数を変更できる。列の桁数を縮小する場合、既存データの最大桁数より小さくすることはできない。 ALTER TABLE emp MODIFY (ename VARCHAR2(100)) テーブルからカラムを削除する 無効にされたトリガはシステム上に存在し続けますが、トリガイベントが発生したとしても実行されません。 MAINは、インラインで保持されていて、圧縮可能なデータに使用します。 つまり、変換対象の列と同様に、その他の列も参照することができます。 そのため、PostgreSQL では既存のテーブルに変更を加えるための一連のコマンドが用意されています。テーブル内のデータを変更するという概念ではないことに注意してください。 コマンドは以下の通りです。, (自動生成された$2といった制約名を扱う場合は、有効な識別子となるように二重引用符で括る必要があることを忘れないでください。), 列の削除に関して、何かが依存している制約を削除する場合にはCASCADEを付ける必要があります。例として、参照されている列に付いている一意またはプライマリキー制約に依存している外部キー制約を削除する場合です。, これは、非NULL制約以外の全ての制約型に適用できます。 デフォルトの設定は、sql_inheritance設定オプションで変更できます)。, 削除された列や制約に依存しているオブジェクト(例えば、削除された列を参照しているビューなど)を、自動的に削除します。, 依存しているオブジェクトがある場合、列または制約の削除要求を拒否します。 CASCADEを追加することにより列に依存する全てを消去することができます。, テーブル制約として記述できない非NULL制約を追加するには、次の構文を使用します。, 制約は即座に検査されますので、制約を追加する前にテーブル内のデータがこれに従っている必要があります。, 制約を削除するには、その制約名を知る必要があります。 対象として、0から1000までの範囲の値を設定可能です。 Postgresql-varcharカラムのサイズを変更する (6) . パラメータによりこれは数値となることも文字列となることもあります。, このテーブルに関連付ける、または、このテーブルから関連付けを取り除く親テーブルです。, ADD COLUMNによって列を追加した時、テーブル内の既存行に追加された列は、全てデフォルト値(DEFAULTが指定されていない場合はNULL)で初期化されます。, NULLではないデフォルト値を持つ列を追加したり、既存の列の型を変更するには、テーブル全体の書き換えが必要になります。 しかし、もし列が他のテーブルの外部キー制約として参照されている場合は、PostgreSQLでは暗黙のうちに制約を消去しません。 非NULL制約をドロップするには、次のようにします。, これはテーブル内の既存の行には何も影響を与えないことに注意してください。これは将来のINSERTコマンドのために単純にデフォルトを変えるだけです。, これは、デフォルトをNULLに設定することと同等です。 したがって、列の削除は短時間で行えます。 Webエンジニアの森脇です。 PostgreSQLで、サービス稼働中に安易にALTER TABLE等を実行すると、ダウンタイムに繋がることがあります。 なぜなら NULL値が暗黙的にデフォルトとなっているからです。, これは、その列の既存の項目が新しい型に暗黙的キャストにより変換できる場合にのみ成功します。 書き換え処理によって、テーブル内の不要となった領域が除去されるからです。 ただし、スーパーユーザはすべてのテーブルの所有者を変更することができます)。, 変更対象となる既存のテーブルの名前です(スキーマ修飾名も可)。 したがって、古い型から新しい型への暗黙キャストや代入キャストが存在しない場合、USINGが指定されていても、ALTER TYPEがデフォルト値の変換に失敗する可能性があります。