HATA'ya neden olan nedir: Başvurulan tablo için verilen anahtarlarla eşleşen benzersiz bir kısıtlama yok mu?


165

Aşağıdaki örnek tablo yapısı bir HATA verir: başvurulan tablo için verilen anahtarlarla eşleşen benzersiz bir kısıtlama yoktur ve bir süredir ona baktığımda bu hatanın neden bu durumda ortaya çıktığını anlayamıyorum.

BEGIN;

CREATE TABLE foo (
    name                VARCHAR(256) PRIMARY KEY
);

CREATE TABLE bar(
    pkey        SERIAL PRIMARY KEY,
    foo_fk      VARCHAR(256) NOT NULL REFERENCES foo(name), 
    name        VARCHAR(256) NOT NULL, 
    UNIQUE (foo_fk,name)
);

CREATE TABLE baz(   
    pkey            SERIAL PRIMARY KEY,
    bar_fk          VARCHAR(256) NOT NULL REFERENCES bar(name),
    name            VARCHAR(256)
);

COMMIT;

Yukarıdaki kodu çalıştırmak, bana mantıklı gelmeyen aşağıdaki hatayı veriyor, bu hatanın neden ortaya çıktığını herkes açıklayabilir. Postgres kullanıyorum 9.1

NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "foo_pkey" for table "foo"
NOTICE:  CREATE TABLE will create implicit sequence "bar_pkey_seq" for serial column "bar.pkey"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "bar_pkey" for table "bar"
NOTICE:  CREATE TABLE / UNIQUE will create implicit index "bar_foo_fk_name_key" for table "bar"
NOTICE:  CREATE TABLE will create implicit sequence "baz_pkey_seq" for serial column "baz.pkey"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "baz_pkey" for table "baz"
ERROR:  there is no unique constraint matching given keys for referenced table "bar"


********** Error **********

ERROR: there is no unique constraint matching given keys for referenced table "bar"
SQL state: 42830

Yanıtlar:


211

Bunun nedeni, tablodaki namesütunun EŞSİZ kısıtlamasına barsahip olmamasıdır .

Yani 2 satır var hayal baradını içeren masaya 'ams've bir satır ekleyin bazile 'ams'ilgili bar_fk, üzerinde hangi satırın baro eşleşen iki sıra olmadığından atıfta olurdu?


1
mükemmel kısa ve kesin ve kolay anlaşılır açıklama!
Alex

83

Postgresql'de tüm yabancı anahtarlar üst tablodaki benzersiz bir anahtara başvurmalıdır , bu nedenle bartablonuzda bir unique (name)dizine sahip olmanız gerekir .

Ayrıca bkz. Http://www.postgresql.org/docs/9.1/static/ddl-constraints.html#DDL-CONSTRAINTS-FK ve özellikle:

Son olarak, bir yabancı anahtarın birincil anahtar olan veya benzersiz bir kısıtlama oluşturan sütunlara başvurması gerektiğini belirtmeliyiz .

Vurgu benim.


25
beyan edilen PK neden benzersiz bir kısıtlama olarak görülmüyor? benzersiz olmayan bir PK'ye sahip olabilirsiniz gibi değil ...
amfibi

2
"Gösterdiği" tabloda benzersiz olmalıdır, çünkü değilse, veritabanı motorunun gerçekte hangi satırdan bahsettiğinizi bilme yolu yoktur.
Matteo Tassinari

Bileşik anahtarlar? @amphibient
Charming Robot

1
Ana tablodaki referans sütunda benzersiz bir anahtara sahip olmanın yalnızca postgresql'de gerekli olmadığını düşünüyorum, aynı zamanda oracle, sql server vb. Gibi diğer RDBMS'ler de gerekli.
Mufachir Hossain

2
Cevabın, üst tabloda bileşik benzersiz bir kısıtlamanın veya birincil anahtarın gerekli olduğu bileşik yabancı anahtarlar için de doğru olduğuna dikkat edin.
Ninjakannon

9

Yaptığınız UNIQUEgibi bir tablo düzeyinde kısıtlama yaptığınızda, sizin tanımlamanız biraz bileşik birincil anahtar gibidir, bkz. ddl kısıtlamaları , işte bir özet

"This specifies that the *combination* of values in the indicated columns is unique across the whole table, though any one of the columns need not be (and ordinarily isn't) unique."

bu, kombinasyonun benzersiz olması ve bu yabancı anahtar kısıtlamanızla eşleşmemesi koşuluyla, her iki alanın da muhtemelen benzersiz olmayan bir değere sahip olabileceği anlamına gelir .

büyük olasılıkla kısıtlamanın sütun düzeyinde olmasını istersiniz. daha sonra bunları tablo seviyesi kısıtlamaları olarak tanımlamak yerine UNIQUE, sütun tanımının sonuna name VARCHAR(60) NOT NULL UNIQUEher alan için ayrı tablo seviyesi kısıtlamaları gibi 'ekleyin' veya belirtin.


Benim durumumda sütun seviyesi kısıtlaması işe yaramayacak Gerçekten bir bileşik birincil anahtar tanımlamalıyım, ancak ondan geri çekildim çünkü onu JPA ile eşleştirmek biraz acı :)
ams

7

Benzersiz bir kısıtlama olarak ad sütununa sahip olmalısınız. İşte sorunlarınızı değiştirmek için 3 satırlık bir kod

  1. İlk önce bu kodu yazarak birincil anahtar kısıtlamalarını bulun

    \d table_name
    

    altta böyle gösteriliyorsun "some_constraint" PRIMARY KEY, btree (column)

  2. Kısıtlamayı kaldırın:

    ALTER TABLE table_name DROP CONSTRAINT some_constraint
    
  3. Mevcut olanla yeni bir birincil anahtar sütunu ekleyin:

    ALTER TABLE table_name ADD CONSTRAINT some_constraint PRIMARY KEY(COLUMN_NAME1,COLUMN_NAME2);
    

Bu kadar.

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.