2015-10-30 46 views
1

由於某種原因,我得到一個錯誤*在我的代碼。我對PostgresSQL很陌生,只是SQL。什麼導致了這個錯誤?錯誤:沒有唯一的約束匹配給定的鍵

*沒有與參考表「tech」的給定鍵匹配的唯一約束。

BEGIN; 

CREATE TABLE Person (
    person_id SERIAL PRIMARY KEY, 
    firstname VARCHAR(128), 
    lastname VARCHAR(128), 
    email_adr VARCHAR(128), 

    UNIQUE(person_id, email_adr) 
); 

CREATE TABLE Phone (
    person_id INT REFERENCES Person(person_id), 
    phone_nr INT PRIMARY KEY, 

    UNIQUE(phone_nr) 
); 


CREATE TABLE Tech (
    tech_id INT REFERENCES Person(person_id), 
    username VARCHAR(80) PRIMARY KEY, 
    password VARCHAR(80) NOT NULL, 
    location Varchar(128), 

    UNIQUE(username, tech_id) 
); 

CREATE TABLE Customer (
    customer_id INT REFERENCES Persons(person_id), 
    addresse  VARCHAR(255) NOT NULL, 

    UNIQUE(customer_id) 
); 

CREATE TABLE Task (
    task_id  SERIAL PRIMARY KEY, 
    payment  MONEY, 
    tech  INT REFERENCES Tech(tech_id)   NOT NULL, 
    customer INT REFERENCES Customer(customer_id) NOT NULL, 
    start_date DATE         NOT NULL, 
    end_dato DATE, 

    UNIQUE(tech, customer, start_date, end_date) 
); 

COMMIT; 

回答

2

在表Task你試圖通過tech_id引用表Tech。爲此,您必須在Tech中添加UNIQUE CONSTRAINTtech_id。 現在在表Tech你有UNIQUE(username, tech_id),這意味着tech_id列的值可能會增加一倍。

Tech 
------------------------------- 
tech_id  username, .... 
------------------------------ 
1   'John' 
2   'Tony' 
1   'Nataly' 

Acctually的更好的主意是PRIMARY KEY設定基準,所以你的情況usernameTech

如果您想要保留結構中存在問題的方式,您應該在Tech列中添加UNIQUE(tech_id)

+0

這不是我所做的嗎? 「UNIQUE(username,tech_id)」 編輯:啊,我明白了。讓我檢查 – Perelan

+0

@ServO不,因爲我在例子**'UNIQUE(username,tech_id)中寫入'意味着這對列應該通過唯一的**。 (1,'John'),(1,'Nataly')在這方面是獨一無二的。只有列tech_id'不是。 –

+0

這解釋了很多。非常感謝你! :) – Perelan

0

您對這段代碼有什麼看法?

BEGIN; 

CREATE TABLE Person (
    person_id SERIAL PRIMARY KEY, 
    firstname VARCHAR(128), 
    lastname VARCHAR(128), 
    email_adr VARCHAR(128), 

    UNIQUE(person_id), 
    UNIQUE(email_adr) 
); 

CREATE TABLE Phone (
    person_id INT, 
    phone_nr INT PRIMARY KEY, 
); 


CREATE TABLE Tech (
    tech_id INT, 
    username VARCHAR(80) PRIMARY KEY, 
    password VARCHAR(80) NOT NULL, 
    location Varchar(128), 

    FOREIGN KEY(tech_id) REFERENCES Person(person_id), 
    UNIQUE(username), 
    UNIQUE(tech_id) 
); 

CREATE TABLE Customer (
    customer_id INT REFERENCES Persons(person_id), 
    addresse  VARCHAR(255) NOT NULL, 

    FOREIGN KEY(tech_id) REFERENCES Person(person_id), 
    UNIQUE(customer_id) 
); 

CREATE TABLE Task (
    task_id  SERIAL PRIMARY KEY, 
    payment  MONEY, 
    tech  varchar(80) REFERENCES Tech(username)  NOT NULL, 
    customer INT  REFERENCES Customer(customer_id) NOT NULL, 
    start_date DATE         NOT NULL, 
    end_dato DATE, 

    UNIQUE(tech, customer, start_date, end_date) 
); 

COMMIT; 
+0

這應該有效。但是,正如我所看到的,您可以修改表結構,「技術」和「人」之間的關係是一對一的(這意味着每個用戶名可以由一個人並且只有一個人擁有)?如果是這樣,我寧願考慮將'Tech'中的'PRIMARY KEY'更改爲'tech_id',並將'Task'中的'tech'列更改爲'tech_id INT參考Tech(tech_id)NOT NULL,'。 「INT」上的「PRIMARY KEY」和「FOREIGN KEY」檢查可能比文本類型便宜。 –

+0

@ Gabriel'sMessanger啊,我會盡力去做。但我有最後一個問題。我已經在ORM(2)中創建了一個SQL模型,並且在該模型中,我指定在Task中,end_date必須大於start_date - 如何使用代碼執行此操作? – Perelan

+0

你的意思是SQL代碼? ['CHECK CONSTRAINT'就是你要找的東西](http://www.postgresql.org/docs/9.4/static/ddl-constraints.html)。在這種情況下,您可以像添加'UNIQUE(...)'一樣添加表格定義'CHECK(end_date> start_date)'。 –

相關問題