2015-10-05 52 views
1

我有一個關於數據庫建模的問題。SQL強制執行1:1關係

假設我有一個表的用戶:

users 
------- 
id:int 
name:text 

而且一個USER_EMAILS:

user_emails 
----------- 
id:int 
user_id:int 
email:text 

我添加了一個外鍵約束上user_emails.user_id這樣,它必須在users.id有效的條目匹配。

但是,這並不能保證每個用戶都有電子郵件。我知道在應用程序級別,我可以很容易地強制執行此操作(即:通過驗證表單中'email'字段是否填充等),但我想知道,在數據庫(sql)級別有一個強制數據完整性的方式? (也就是說,在這種情況下,每個用戶都有一封電子郵件?)

謝謝! :)

+1

只是添加不爲空,但你的標題說是不同於你的文章說的,你想執行,1:1關係或不空值?如果您想要第一個選項,那麼只需忘記user_emails表,然後將該列添加到主表用戶中,如果您想要第二個表,則只需放置非空列或更好地使用兩者。 –

+0

爲什麼不使用觸發器? –

+0

正如@JuanRuizdeCastilla所示,只需在您的電子郵件:文本字段中添加NOT NULL約束即可。 – narendra

回答

1

你必須把你的FK各地

users 
----- 
id:int 
name:text 
user_emails_id:int (NOT NULL) 

user_emails 
----- 
id:int 
email:text (NOT NULL) 

這樣可以強制有在電子郵件表的關係,如果你設置的郵箱值不爲空,然後你強迫至少有在列中的條目

編輯基於註釋: 爲了達到用戶收到多封電子郵件,您必須添加一個:M表

users 
----- 
id:int 
name:text 
user_emails_reference_id:int (NOT NULL referencing user_email_references) 

user_email_references 
----- 
id:int 
user_email_id:int (NOT NULL Referencing user_emails) 
user_id:int (NOT NULL Referencing users) 

user_emails 
----- 
id:int 
email:text (NOT NULL) 
+0

,因此,首先插入user_emails,然後是user_emails指派的用戶。這是應該工作 –

+0

謝謝,擴展到這一點,有什麼辦法,我可以允許多個電子郵件的用戶? – MrD

+0

如果你允許一個用戶多個emials然後它不是一個1:1的關係了......但你可以添加一個:m關係表來實現這個目標 – deterministicFail

1

想必,你想允許用戶有多個電子郵件,但只是爲了保證至少有一個。您可以通過執行來相當接近與MySQL的限制:

create table Users (
    UserId int not null primary key, . . . 
    . . . 
    PrimaryEmailId int not null, 
    constraint fk_PrimaryEmailId foreign key (UserId, PrimaryEmailId) references UserEmails(UserId, UserEmailId) 
); 

create table UserEmails (
    UserEmailId int not null primary key, 
    UserId int not null, 
    . . ., 
    unique (UserId, UserEmailId), 
    constraint fk_UserEmails_UserId foreign key (UserId) references Users(UserId) 
); 

這保證:

  • 每個用戶只能有一個主電子郵件。
  • 每個電子郵件都有一個用戶。
  • 主電子郵件與指定的用戶具有相同的用戶。

請注意使用時髦的外鍵關係。參考UserEmailId就足夠了。但是,這並不能保證用戶是一樣的。

您可能還想爲電子郵件本身添加一個唯一約束,以便不同的用戶不能共享一封電子郵件。

+0

謝謝,這很有道理:)事情是通過添加將「PrimaryEmail」字段添加到「用戶」表中我覺得我正在增加開銷。系統應該能夠通過檢查email.person_id列來推斷出用戶的電子郵件存在......但是也許這最好延遲到應用程序層? – MrD