Zaten var olan bir tabloya yabancı anahtar kısıtlaması olan bir sütun nasıl eklenir?


11

Aşağıdaki tablolarım var,

CREATE TABLE users (id int PRIMARY KEY);

-- already exists with data
CREATE TABLE message ();

messagesTabloyu nasıl değiştirebilirim ki,

  1. adlı yeni bir sütun sendereklenir
  2. tabloya senderbaşvuran yabancı anahtar neredeusers

Bu işe yaramadı

# ALTER TABLE message ADD FOREIGN KEY (sender) REFERENCES users;
ERROR:  column "sender" referenced in foreign key constraint does not exist

Bu ifade de sütun oluşturmuyor mu?


3
Referans vermeden önce sütunu oluşturmanız gerekir. Ayrıca burada ALTER TABLE belgelerini okumaya çalışacağım ve örneklere çok dikkat ediyorum .
Kassandry

Hassan, DDL'yi kullanmak için bu soruyu temizledim ve çalışmayan şeyleri kaldırdım. Bunun soruyu cevaplayıp karşılamadığına bakın: dba.stackexchange.com/a/202564/2639 . Bu düzenlemelerden herhangi birini reddetmekten çekinmeyin, bunu sadece gelecek nesiller için temizlemek istedim.
Evan Carroll

Yanıtlar:


18

Nispeten kolay olan - sadece bir adım daha eklemeniz gerekir.

FOREIGN KEYSütun varolması gerekir bunu bir hale getirmek için FK. Aşağıdakileri yaptım ( buradan ve belgelerden ):

CREATE TABLE x(t INT PRIMARY KEY);

CREATE TABLE y(s INT);

ALTER TABLE y ADD COLUMN z INT;    

ALTER TABLE y
  ADD CONSTRAINT y_x_fkey FOREIGN KEY (z)
      REFERENCES x (t)
      ON UPDATE CASCADE ON DELETE CASCADE;

Dikkat edilmesi gereken birkaç nokta:

HER ZAMAN yabancı anahtarlarınıza anlamlı isimler verin. "SYS_C00308108" anahtarının ihlal edildiğinin söylenmesi çok yararlı değildir. Keman bakın burada anahtar adı keman için keman değişir bu koşullar altında Oracle'ın davranışı için, ama) _... SYS ile başlayan bazı keyfi dizedir

İfadenizi göz önünde bulundurarak:

ALTER TABLE message ADD FOREIGN KEY (sender) REFERENCES users;

RDBMS, istediğiniz alanı otomatik olarak başvurulan alanla eşleşen veri türüyle oluşturabiliyorsa, "olması güzel" olur. Söyleyebileceğim tek şey, DDL'yi değiştirmenin nadiren kullanılan bir işlem olduğu ve düzenli olarak yapmak istediğiniz bir şey olmadığıdır. Ayrıca, zaten oldukça önemli bir belgeye ekleme riski de vardır.

En azından PostgreSQL makul bir şey yapmaya çalışır - tablo adını, FOREIGN KEYalan adını birleştirir _fkeyve hatta DETAIL: Key (sender_id)=(56) is not present in table "user_".bir insana mantıklı gelebilecek bir şey verir - buraya bakın .


2
Yabancı anahtarlarımı hiç adlandırmam. Özerkleşiyorlar ve genellikle oldukça faydalılar. Örneğin, bu bağlamdaki varsayılan ad "y_z_fkey". Bundan daha iyi bir isim iddia ediyorum y_x_fkeyihlalinizden sen yerleştirme sütun size değil çünkü içine o hataya neden. Nereye gittiğini umursamıyorum. Genel bir kural olarak, ASLA fkey'lerinizi adlandırmamalı ve PostgreSQL'in varsayılanı tarafından işlemesine izin vermemelisiniz.
Evan Carroll

Ayrıca, ON UPDATE CASCADE ON DELETE CASCADE;bir örnekte varsayılanları , özellikle de sebepsiz olarak geçersiz kılmak istemeyebilirsiniz . Örneği daha karmaşık hale getirir ve ne olduğunu açıklamaktan rahatsız olmazsınız. Ben normalde silmelerin art arda sıralanmasını istemiyorum.
Evan Carroll

1
Ben hep isim şirket / proje karar verdiğini konvansiyonuna göre, FKS. Tutarlı olduğu sürece y_x_fkeyya y_z_fkeyda ya da x__y_FKtutarlı olduğu sürece fazla bir önemi yoktur .
ypercubeᵀᴹ

Eğer sözleşme yapıyorsanız bunu çok kabul ediyorum - bir sözleşme seçin ve ona uyun ve / veya daha önce sistemle kullanılmış / kullanılan sözleşmelere uyduğunuzdan emin olun.
Vérace

- @EvanCarroll eğer PostgreSQL'in kongre projesinin veya bir önceki PostgreSQL olmayabilir sistemlerde karar - bir sistem de, üzerinde başlamış olabilir diyelim ki, Oracle veya PostgreSQL'in kongre (ler) olmayabilir diğer sistem. Bir hata durumunda x_y_z_fk'ın mümkün olan en fazla bilgiyi verebileceğini iddia edebilirsiniz! Bir şey ve Seçim sopa (olursa olsun iyi nasıl) sizin için kuralları karar benim sloganı kendisine, ama bir RDBMS'yi izin vermeyin!
Vérace

8

Neden herkesin bunu iki adımda yapmanız gerektiğini söylediğinden emin değilim. Aslında, bilmiyorsunuz . Bir eklemeye çalıştı FOREIGN KEYtasarım gereği, varsayar ki, sütun vardır ve sütun yoksa o hatayı atar. Eğer eklerseniz COLUMN, bunu bir hale açıkça yapabilirsiniz FOREIGN KEYile oluşturulması üzerinde REFERENCES,

ALTER TABLE message
  ADD COLUMN sender INT
  REFERENCES users;  -- or REFERENCES table(unique_column)

İyi çalışacak. Sen edebilirsiniz sözdizimini görmek ALTER TABLE, burada

ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ]
action [, ... ]

İle "eylem" olarak

ADD [ COLUMN ] [ IF NOT EXISTS ] column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] ]

Bu örnekler dokümanlarda bile,

ALTER TABLE distributors
  ADD CONSTRAINT distfk
  FOREIGN KEY (address)
  REFERENCES addresses (address);

ALTER TABLE distributors
  ADD CONSTRAINT distfk
  FOREIGN KEY (address)
  REFERENCES addresses (address)
  NOT VALID;

Ancak tüm bunlar gerekli değildir, çünkü otonom ve birincil anahtar çözünürlüğüne güvenebiliriz (yalnızca tablo adı belirtilmişse, birincil anahtara başvuruyorsunuz).


0

DURUM1: Yeni bir tablo oluştururken yabancı anahtar oluşturmanız gerekiyorsa

CREATE TABLE table1(
id SERIAL PRIMARY KEY,
column1 varchar(n) NOT NULL,
table2_id SMALLINT REFERENCES table2(id)
); 

Yukarıdaki komutlar 'table1' adında bir tablo ve 'id' (Birincil anahtar), 'column1', 'table2_id' (table2'nin id sütununa gönderme yapan table1'in yabancı anahtarı) adında üç sütun oluşturur.

DATATYPE 'seri', bu veri türünü otomatik olarak oluşturulan bir sütun olarak kullanan sütunu yapar, tabloya değerler eklerken bu sütundan hiç bahsetmenize gerek yoktur ya da değer yerinde tırnak işaretleri olmadan 'varsayılan' verebilirsiniz.

Tablonun dizinine her zaman 'tablename_pkey' değerine sahip birincil anahtar sütunu eklenir.

Tablo oluşturma zamanında yabancı anahtar eklenirse, '(present_table_name) _ (foreign_key_id_name) _fkey' deseniyle bir CONSTRAINT eklenir.

Bir yabancı anahtar eklerken, sütun adının yanına 'REFERANSLAR' anahtar kelimesini girmeliyiz çünkü postgres'e bu sütunun bir tabloya atıfta bulunduğunu ve referansların yanında referans için tabloyu vermeliyiz ve köşeli parantez içinde başvurulan tablonun sütun adı, genellikle yabancı anahtarlar birincil anahtar sütunları olarak verilir.

DURUM 2: Mevcut sütundaki mevcut bir tablonun yabancı anahtarını istiyorsanız

ALTER TABLE table1
ADD CONSTRAINT table1_table2_id_id_fkey
FOREIGN KEY (table2_id) REFERENCES table2(id);

NOT: YABANCI ANAHTAR ve REFERANSLAR tabel2'den sonra parantez '()' zorunludur, aksi takdirde postgres hata verir.


0

Sorunu biliyorum. Sütun adları farklıdır. Belki bir sütunda, sütun adınızdan sonra ek bir boşluk vardır, bu yüzden lütfen sütun adlarınızın tamamen aynı şekilde adlandırıldığından emin olun.


1
OP sordu: Bu ifade de sütun oluşturmuyor mu? Dolayısıyla bunun olmasını beklediği açıktır.
Laurenz Albe
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.