nullを許可しないPostgresqlデータベースに列を追加するにはどうすればよいですか?


243

次のクエリ(インターネット用にサニタイズ)を使用して、新しい「NOT NULL」列をPostgresqlデータベースに追加します。

ALTER TABLE mytable ADD COLUMN mycolumn character varying(50) NOT NULL;

このクエリを実行するたびに、次のエラーメッセージが表示されます。

ERROR:  column "mycolumn" contains null values

私は困惑しています。どこがいけないの?

注:主にpgAdmin III(1.8.4)を使用していますが、ターミナル内からSQLを実行したときにも同じエラーが発生しました。

回答:


400

デフォルト値を設定する必要があります。

ALTER TABLE mytable ADD COLUMN mycolumn character varying(50) NOT NULL DEFAULT 'foo';

... some work (set real values as you want)...

ALTER TABLE mytable ALTER COLUMN mycolumn DROP DEFAULT;

1
素晴らしい解決策。このための構文を確認するために、何らかの理由でオンラインのpostgresドキュメントにアクセスできませんでした。
ショーンブライト

4
@SeanBright、次のようにすることでオフラインでpostgresドキュメントにアクセスできますman ALTER_TABLE :)
allan.simon

@ allan.simon PostgreSQLを使用したことがなく、どこにもインストールしていません。
Sean Bright、

2
明確にするために:デフォルト値は、既存の行を更新するためにのみ必要です。そのため、すぐに削除できます。テーブルが変更されたとき、既存のすべての行が更新されました(明らかに時間がかかる場合があります)
MSalters '26

2
別の列を使用して既存の行の初期値を計算する場合、これは機能しません。j_random_hackerの答えはそれを可能にし、より堅牢にします。
jpmc26 2016

82

他のユーザーが確認したように、null許容列を作成するか、DEFAULT値を指定する必要があります。それが十分に柔軟でない場合(たとえば、何らかの方法で各行の新しい値を個別に計算する必要がある場合)、PostgreSQLでは、すべてのDDLコマンドをトランザクション内で実行できるという事実を使用できます。

BEGIN;
ALTER TABLE mytable ADD COLUMN mycolumn character varying(50);
UPDATE mytable SET mycolumn = timeofday();    -- Just a silly example
ALTER TABLE mytable ALTER COLUMN mycolumn SET NOT NULL;
COMMIT;

7
トランザクション内であっても、NOT NULLは直ちに適用されるため、最初に列を追加し、値を入力してから、NOT NULLを追加する必要があります—この回答のように。(postgres 9.6でテスト済み)
Beni Cherniavsky-Paskin 2017年

48

テーブルに行が既に存在するため、ALTERステートメントはNULL、既存のすべての行に対して新しく作成された列に挿入しようとしています。列をallowingとして追加しNULL、次に列に必要な値を入力して、NOT NULL後でそれを設定する必要があります。


7
それを行う方法の例は本当に良かったでしょう。それ以外の場合、Lucのソリューションはより完全ですぐに使用できるようです。
Victor Farazdagi、

5

デフォルトを定義するか、Seanが言うことを実行して、既存の行に入力するまでnull制約なしで追加する必要があります。


2

デフォルト値が適切であると想定して、デフォルト値の指定も機能します。


2
これにより、(例として)デフォルト値で列を作成するための修正された構文を提供するための回答が改善されます。
hardmath

1

または、追加の列を含むtempとして新しいテーブルを作成し、必要に応じて操作しながらデータをこの新しいテーブルにコピーして、null不可の新しい列を埋め、2段階の名前変更でテーブルを交換します。

はい、より複雑ですが、ライブテーブルで大きなUPDATEが必要ない場合は、この方法で行う必要がある場合があります。


3
私はあなたを-1にしませんでしたが、これには微妙な問題があると思います-たとえば、既存のインデックス、トリガー、ビューは、名前を変更した後でも、元のテーブルを引き続き参照していると思います名前ではなく、テーブルのrelid(変更されません)。
j_random_hacker 2009

1
はい、新しいテーブルは、インデックスの追加など、元のテーブルの正確なコピーである必要があると述べるべきでした。短すぎるのが悪い。この理由は、ライブである可能性があるテーブルに対してALTERを実行することには微妙な困難があり、場合によってはステージングする必要があるためです。
alphadogg 2009

たとえば、DEFAULTアプローチを使用して、そのデフォルト値を各行に追加します。これを行うときにPostgresがテーブルをロックする方法がわかりません。または、列の順序が重要な場合は、ALTERコマンドを使用して列を追加することはできません。
alphadogg 2009

十分に公正で、ALTER TABLEはPostgreSQLのドキュメントに従ってテーブルをロックしますが、非トランザクションのアプローチは、テーブルが実際にライブである場合、変更を失うリスクがあります。また、列の順序に依存するすべてのコードが壊れていることをお勧めします(もちろん、それはあなたの制御の外にある可能性があります)。
j_random_hacker 2009

2
このアプローチは、テーブルも外部キーインデックスによって参照されている場合、それらもすべて再作成する必要があるため、特に問題になります。
Aryeh Leib Taurog 2015年

0

このクエリはnullを自動更新します

ALTER TABLE mytable ADD COLUMN mycolumn character varying(50) DEFAULT 'whatever' NOT NULL;

-6

これは私のために働きました::)

ALTER TABLE your_table_name ADD COLUMN new_column_name int;

2
NOT NULLクエリに制約はありません。もちろん動作しています。
シルヴァン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.