Postgresql veritabanına null değerlerine izin vermeyen bir sütunu nasıl ekleyebilirim?


243

Aşağıdaki sorguyu (Internet için dezenfekte edilmiş) kullanarak Postgresql veritabanına yeni bir "NOT NULL" sütunu ekliyorum:

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

Bu sorguyu her çalıştırdığımda, aşağıdaki hata iletisini alıyorum:

ERROR:  column "mycolumn" contains null values

Şoktayım. Nerede yanlış gidiyorum?

NOT: Öncelikle pgAdmin III (1.8.4) kullanıyorum, ancak SQL'i Terminal içinden çalıştırdığımda aynı hatayı aldım.

Yanıtlar:


400

Varsayılan bir değer ayarlamanız gerekir.

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
Güzel çözüm. Bunun için sözdiziminin ne olacağını görmek için çevrimiçi postgres belgelerine bir nedenle erişemedim.
Sean Bright

4
@SeanBright, postgres man ALTER_TABLE
doc'a

@ allan.simon Daha önce hiç PostgreSQL kullanmadım ve hiçbir yere kurmadım.
Sean Bright

2
Açıklığa kavuşturmak için: varsayılan değer yalnızca mevcut satırları güncellemek için gereklidir, bu nedenle hemen ardından bırakılabilir. Tablo değiştiğinde mevcut tüm satırlar güncellendi (ki bu biraz zaman alabilir, belli ki)
MSalters

2
Varolan satırların başlangıç ​​değerini hesaplamak için başka bir sütun kullanmak istiyorsanız bu işe yaramaz. j_random_hacker'ın cevabı buna izin vererek daha sağlam hale getirir.
jpmc26

82

Diğerlerinin de gözlemlediği gibi, boş değerli bir sütun oluşturmanız veya bir VARSAYILAN değeri sağlamanız gerekir. Bu yeterince esnek değilse (örneğin, her satır için ayrı ayrı hesaplanacak yeni değere ihtiyacınız varsa), PostgreSQL'de tüm DDL komutlarının bir işlem içinde yürütülebileceği gerçeğini kullanabilirsiniz:

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
bir işlemde bile, NOT NULL hemen uygulanır, bu nedenle önce sütun, dolgu değerleri eklemeli, ardından NOT NULL eklemelisiniz - bu cevap gibi. (postgres 9.6'da test edildi)
Beni Cherniavsky-Paskin

48

Tabloda satırlar zaten bulunduğundan, ALTERifade NULLvarolan tüm satırlar için yeni oluşturulan sütuna eklemeye çalışıyor . Sütunu izin olarak eklemeniz NULL, ardından sütunu istediğiniz değerlerle doldurmanız ve daha sonra bunu ayarlamanız gerekir NOT NULL.


7
Bunun nasıl yapılacağına dair bir örnek gerçekten güzel olurdu. Aksi halde Luc'un çözümü daha eksiksiz ve kullanıma hazır görünüyor.
Victor Farazdagi

5

Bir varsayılan tanımlamanız veya Sean'ın söylediklerini yapmanız ve varolan satırlara girene kadar null kısıtlaması olmadan eklemeniz gerekir.


2

Varsayılan bir değer belirtmek, varsayılan bir değerin uygun olduğu varsayılarak da işe yarayacaktır.


2
Değiştirilmiş sözdizimini varsayılan değerle sütun (örnek olarak) oluşturmak için verilen yanıtı geliştirir.
hardmath

1

Ya da, ekstra sütunu ile geçici olarak yeni bir tablo oluşturun, boş bırakılamayan yeni sütunu doldurmak için gerektiği gibi işlerken verileri bu yeni tabloya kopyalayın ve sonra tabloyu iki adımlı bir ad değişikliği ile değiştirin.

Evet, daha karmaşıktır, ancak canlı bir tabloda büyük bir GÜNCELLEME istemiyorsanız bunu bu şekilde yapmanız gerekebilir.


3
Sizi -1 yapmadım, ancak bence bununla ilgili küçük zorluklar olabilir - örneğin, mevcut endekslerin, tetikleyicilerin ve görünümlerin, yeniden adlandırdıktan sonra bile orijinal tabloya başvurmaya devam edeceğini tahmin ediyorum. isminden ziyade tablonun relid (değişmez).
j_random_hacker

1
Evet, yeni tablonun, indeksler ve benzerlerini eklemek de dahil olmak üzere orijinalin tam bir kopyası olması gerektiğini belirtmeliydim. Çok kısa olduğum için kötüyüm. Bunun nedeni, bir ALTER'i canlı olabilen bir tablo üzerinde gerçekleştirmenin ince güçlükleri olması ve bazen de sahneye koymanız gerekir.
alphadogg

Örneğin, VARSAYILAN yaklaşımını kullanarak, bu varsayılan değeri her satıra eklersiniz. Bunu yaparken Postgres'in bir tabloyu nasıl kilitlediğinden emin değilim. Veya sütun sırası önemliyse, ALTER komutuyla bir sütun ekleyemezsiniz.
alphadogg

Oldukça adil, ALTER TABLE PostgreSQL belgelerine göre tabloyu kilitler, ancak işlem dışı yaklaşımınız tablo gerçekten canlıysa değişiklikleri kaybetme riskiyle karşı karşıyadır. Ayrıca sütun sırasına dayanan herhangi bir kod kırık (tabii ki sizin kontrolünüz dışında olabilir) öneririz.
j_random_hacker

2
Tablonun yabancı anahtar dizinleri tarafından referans alınıyor olması durumunda bu yaklaşım özellikle sorunludur, çünkü bunların hepsinin de yeniden oluşturulması gerekir.
Aryeh Leib Taurog

0

bu sorgu null değerlerini otomatik olarak güncelleyecektir

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

-6

Bu benim için çalıştı: :)

ALTER TABLE your_table_name ADD COLUMN new_column_name int;

2
Yok NOT NULLSorgunuzda kısıtlama . Tabii ki çalışıyor.
Sylvain
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.