สิ่งที่ทำให้เกิดข้อผิดพลาด: ไม่มีการจับคู่ข้อ จำกัด ที่ไม่ซ้ำกันสำหรับคีย์อ้างอิงตาราง


154

ตัวอย่างโครงสร้างตารางด้านล่างให้ข้อผิดพลาด: ไม่มีการจับคู่ข้อ จำกัด ที่ไม่ซ้ำกันสำหรับคีย์อ้างอิงตารางและมีจ้องมองมันในขณะที่ตอนนี้ฉันไม่สามารถคิดออกว่าทำไมข้อผิดพลาดนี้เกิดขึ้นในสถานการณ์นี้

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;

การเรียกใช้รหัสข้างต้นทำให้เกิดข้อผิดพลาดต่อไปนี้ซึ่งไม่สมเหตุสมผลสำหรับฉันทุกคนสามารถอธิบายได้ว่าทำไมข้อผิดพลาดนี้เกิดขึ้น ฉันใช้ postgres 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

คำตอบ:


188

เป็นเพราะnameคอลัมน์ในbarตารางไม่มีข้อ จำกัดUNIQUE

ดังนั้นคิดว่าคุณมี 2 แถวในbarตารางที่มีชื่อ'ams'และคุณแทรกแถวบนbazที่มี'ams'ในbar_fkที่แถวบนbarมันจะหมายเนื่องจากมีสองแถวจับคู่?


1
คำอธิบายที่สั้นและแม่นยำและจับได้ง่ายสมบูรณ์แบบ!
อเล็กซ์

79

ใน postgresql คีย์ต่างประเทศทั้งหมดจะต้องอ้างอิงถึงคีย์ที่ไม่ซ้ำกันในตารางหลักดังนั้นในbarตารางของคุณคุณต้องมีunique (name)ดัชนี

ดูhttp://www.postgresql.org/docs/9.1/static/ddl-constraints.html#DDL-CONSTRAINTS-FKและโดยเฉพาะ:

ในที่สุดเราควรพูดถึงว่าคีย์ต่างประเทศจะต้องอ้างอิงคอลัมน์ที่เป็นคีย์หลักหรือรูปแบบข้อ จำกัด ที่ไม่ซ้ำกัน

เน้นการขุด


21
ทำไม PK ที่ประกาศไม่ถือว่าเป็นข้อ จำกัด ที่ไม่ซ้ำกัน มันไม่เหมือนที่คุณสามารถมี PK ที่ไม่เป็น
เอกสิทธิ์

2
มันจะต้องไม่ซ้ำกันในตารางมัน "ชี้ไปที่" เพราะถ้ามันไม่ได้เครื่องมือฐานข้อมูลจะไม่มีทางรู้ว่าแถวที่คุณกำลังอ้างถึงจริง ๆ
Matteo Tassinari

แป้นผสม? @amphibient
หุ่นยนต์ที่มีเสน่ห์

1
ผมคิดว่ามีความสำคัญที่ไม่ซ้ำกันในคอลัมน์อ้างอิงในตารางผู้ปกครองไม่จำเป็นต้องใช้ใน PostgreSQL เท่านั้น แต่ยังอื่น ๆ RDBMSs เกินไปเช่น Oracle, SQL เซิร์ฟเวอร์ ฯลฯ
Mufachir Hossain

2
โปรดทราบว่าคำตอบนั้นเป็นจริงเช่นกันสำหรับปุ่มต่างประเทศแบบผสมซึ่งจำเป็นต้องมีข้อ จำกัด ที่ไม่ซ้ำกันหรือคีย์หลักในตารางหลัก
Ninjakannon

8

เมื่อคุณทำUNIQUEตามข้อ จำกัด ระดับตารางตามที่คุณได้กำหนดไว้สิ่งที่การกำหนดของคุณจะเป็นเช่นคีย์หลักแบบคอมโพสิตดูข้อ จำกัด ของ ddlนี่คือสารสกัด

"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."

นี่หมายความว่าฟิลด์ใดฟิลด์หนึ่งอาจมีค่าที่ไม่ซ้ำกันหากการรวมกันนั้นไม่ซ้ำกันและสิ่งนี้ไม่ตรงกับข้อ จำกัด กุญแจต่างประเทศของคุณ

เป็นไปได้ว่าคุณต้องการให้ข้อ จำกัด อยู่ที่ระดับคอลัมน์ ดังนั้นจึงควรกำหนดให้เป็นข้อ จำกัด ระดับตาราง 'ผนวก' UNIQUEต่อท้ายคำจำกัดความของคอลัมน์เช่นname VARCHAR(60) NOT NULL UNIQUEหรือระบุข้อ จำกัด ระดับตารางเฉพาะสำหรับแต่ละฟิลด์


ข้อ จำกัด ระดับคอลัมน์ในสถานการณ์ของฉันจะไม่ทำงานฉันควรกำหนดคีย์หลักแบบผสมจริง ๆ แต่ฉันถอยห่างจากมันเพราะการจับคู่กับ JPA เป็นเรื่องที่เจ็บปวด :)
14154

6

คุณควรมีคอลัมน์ชื่อเป็นข้อ จำกัด ที่ไม่ซ้ำกัน นี่คือรหัส 3 บรรทัดเพื่อแก้ไขปัญหาของคุณ

  1. ก่อนอื่นหาข้อ จำกัด คีย์หลักโดยการพิมพ์รหัสนี้

    \d table_name

    คุณจะแสดงแบบนี้ที่ด้านล่าง "some_constraint" PRIMARY KEY, btree (column)

  2. วางข้อ จำกัด :

    ALTER TABLE table_name DROP CONSTRAINT some_constraint
  3. เพิ่มคอลัมน์คีย์หลักใหม่ที่มีอยู่:

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

นั่นคือทั้งหมด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.