Bagaimana saya bisa menambahkan kolom ke database Postgresql yang tidak memungkinkan nulls?

243

Saya menambahkan kolom "NOT NULL" baru ke basis data Postgresql saya menggunakan kueri berikut (disanitasi untuk Internet):

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

Setiap kali saya menjalankan kueri ini, saya menerima pesan galat berikut:

ERROR:  column "mycolumn" contains null values

Saya bingung. Di mana saya salah?

CATATAN: Saya menggunakan pgAdmin III (1.8.4) terutama, tetapi saya menerima kesalahan yang sama ketika saya menjalankan SQL dari dalam Terminal.

Huuuze
sumber

Jawaban:

400

Anda harus menetapkan nilai default.

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;
Luc M
sumber
1
Solusi bagus Saya tidak bisa membuka dokumen postgres online karena beberapa alasan untuk melihat seperti apa sintaksisnya.
Sean Bright
4
@SeanBright, Anda dapat mengakses postgres doc offline dengan melakukan man ALTER_TABLE :)
allan.simon
@ allan.simon Saya belum pernah menggunakan PostgreSQL sebelumnya dan saya belum menginstalnya di mana pun.
Sean Bright
2
Untuk memperjelas: nilai default hanya diperlukan untuk memperbarui baris yang ada, itulah sebabnya dapat segera dihapus sesudahnya. Semua baris yang ada telah diperbarui ketika tabel diubah (yang mungkin memakan waktu, tentu saja)
MSalters
2
Ini tidak akan berfungsi jika Anda ingin menggunakan kolom lain untuk menghitung nilai awal untuk baris yang ada. Jawaban j_random_hacker memungkinkan untuk itu, membuatnya lebih kuat.
jpmc26
82

Seperti yang telah diamati orang lain, Anda harus membuat kolom yang dapat dibatalkan atau memberikan nilai DEFAULT. Jika itu tidak cukup fleksibel (misalnya jika Anda membutuhkan nilai baru untuk dihitung untuk setiap baris secara terpisah), Anda dapat menggunakan fakta bahwa di PostgreSQL, semua perintah DDL dapat dieksekusi di dalam suatu transaksi:

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;
j_random_hacker
sumber
7
bahkan dalam suatu transaksi, NOT NULL segera diberlakukan, jadi pertama-tama harus menambahkan kolom, mengisi nilai, lalu menambahkan NOT NULL - seperti jawaban ini. (diuji pada postgres 9.6)
Beni Cherniavsky-Paskin
48

Karena baris sudah ada di tabel, ALTERpernyataan berusaha memasukkan NULLke kolom yang baru dibuat untuk semua baris yang ada. Anda harus menambahkan kolom sebagai memungkinkan NULL, lalu isi kolom dengan nilai yang Anda inginkan, dan kemudian setel NOT NULLsetelahnya.

Sean Bright
sumber
7
Contoh cara melakukannya akan sangat menyenangkan. Kalau tidak, solusi Luc tampaknya lebih lengkap dan siap digunakan.
Victor Farazdagi
5

Anda juga perlu mendefinisikan default, atau melakukan apa yang Sean katakan dan menambahkannya tanpa batasan nol sampai Anda mengisinya pada baris yang ada.

Paul Tomblin
sumber
2

Menentukan nilai default juga akan berfungsi, dengan asumsi nilai default sesuai.

Ryan Graham
sumber
2
Itu akan meningkatkan jawaban untuk memberikan sintaks yang diubah untuk membuat kolom dengan nilai default (untuk ilustrasi).
hardmath
1

Atau, buat tabel baru sebagai temp dengan kolom tambahan, salin data ke tabel baru ini sambil memanipulasi seperlunya untuk mengisi kolom baru yang tidak dapat dibatalkan, dan kemudian menukar tabel melalui perubahan nama dua langkah.

Ya, ini lebih rumit, tetapi Anda mungkin perlu melakukannya dengan cara ini jika Anda tidak ingin pembaruan besar di tabel langsung.

alphadogg
sumber
3
Saya tidak -1 Anda, tapi saya pikir mungkin ada kesulitan halus dengan ini - misalnya saya bertaruh bahwa indeks, pemicu dan pandangan yang ada akan terus merujuk ke tabel asli bahkan setelah mengganti nama karena saya pikir mereka menyimpan relid dari tabel (yang tidak berubah) daripada namanya.
j_random_hacker
1
Ya, saya seharusnya menyatakan bahwa tabel baru harus merupakan salinan asli dari yang asli, termasuk menambahkan indeks dan semacamnya. Saya buruk karena terlalu singkat. Alasan untuk ini adalah bahwa ada juga kesulitan halus melakukan ALTER di atas meja yang mungkin hidup, dan kadang-kadang Anda perlu mengaturnya.
alphadogg
Misalnya, menggunakan pendekatan DEFAULT, Anda akan menambahkan nilai default itu ke setiap baris. Tidak yakin bagaimana Postgres mengunci tabel saat melakukan ini. Atau, jika urutan kolom penting, Anda tidak bisa menambahkan kolom dengan perintah ALTER.
alphadogg
Cukup adil, ALTER TABLE memang mengunci tabel sesuai dengan dokumen PostgreSQL, namun pendekatan non-transaksional Anda berisiko kehilangan perubahan jika tabel tersebut benar-benar hidup. Saya juga menyarankan bahwa setiap kode yang bergantung pada urutan kolom rusak (yang mungkin di luar kendali Anda tentu saja).
j_random_hacker
2
Pendekatan ini juga sangat bermasalah jika tabel direferensikan oleh indeks kunci asing karena mereka semua harus diciptakan kembali juga.
Aryeh Leib Taurog
0

kueri ini akan memperbarui nol secara otomatis

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

Ini bekerja untuk saya: :)

ALTER TABLE your_table_name ADD COLUMN new_column_name int;
timxor
sumber
2
Tidak ada NOT NULLbatasan pada kueri Anda. Tentu saja berhasil.
Sylvain