2011-09-05 197 views
6

您好,我有一個關於數據庫設計的簡短問題。我也試過搜索,但找不到我在找什麼。所以這裏是我的問題:1:N關係,其中N必須至少有一個條目

我有兩個數據庫表想法媒體(1:N)。所以基本上這意味着一個想法可以沒有,一個或幾個媒體。但是我問自己是否可以定義表格,即每個創意至少必須有一個媒體。如果這是可能的,我怎麼才能用MS SQL Server 2008實現這一點?

我希望有人能幫助我。

THX很多的幫助

UPDATE: 這是它看起來像此刻:在想法

enter image description here

+2

我不知道如何將'Media'保存在單獨的表格中:如何插入數據?你必須首先插入一個表格,然後插入第二個表格。你可以嘗試的是將第一個'Media'放入'Idea'(去規範化)並聲明這些字段爲'not null' - 但我不會推薦它。用代碼中的某些邏輯而不是數據庫可能會更好。 –

+0

我同意Aleks。我認爲這是一個屬於中間層的業務規則,不在數據庫中。 – David

+0

@Aleks將FK NOT NULL從Idea添加到Media並不少見。這很簡單,是的,他需要首先填充媒體。 – vol7ron

回答

2

首先,有一種設計經驗法則,即表格模擬單個實體類型或實體類型之間的關係,但不是兩者都建模。因此,我設想了三個表,Media(實體),Idea(實體)和IdeasMedia(關係)。附:你知道'媒體'的單數是'中等',對吧? :)

下面是一些標準的SQL-92 DDL,專注於純鍵:

CREATE TABLE Media (MediaID INTEGER NOT NULL UNIQUE); 
CREATE TABLE Idea (IdeaID INTEGER NOT NULL UNIQUE); 
CREATE TABLE IdeasMedia 
(
MediaID INTEGER NOT NULL REFERENCES Media (MediaID), 
IdeaID INTEGER NOT NULL REFERENCES Idea (IdeaID) 
); 
CREATE ASSERTION Idea_must_have_media DEFERRABLE 
    CHECK (
      NOT EXISTS (
         SELECT * 
         FROM Idea AS i 
         WHERE NOT EXISTS (
             SELECT * 
              FROM IdeasMedia AS im 
              WHERE im.MediaID = i.IdeaID 
             ) 
        ) 
     ); 

有一個「雞和蛋」的情景在這裏:沒有引用IdeasMedia但可以不能創建一個主意創建IdeasMedia而不創建Idea

理想的(基於集合的)解決方案將用於SQL標準以支持多種分配,例如,

INSERT INTO Media (MediaID) VALUES (22), 
    INSERT INTO Idea (IdeaID) VALUES (55), 
    INSERT INTO IdeasMedia (MediaID, IdeaID) VALUES (22, 55); 

其中分號表示在這一點約束檢查SQL語句邊界和表示子報表的逗號。

不幸的是,沒有計劃將此基於集合的範例添加到SQL標準。

的SQL-92(程序)解決了這個如下:

BEGIN TRANSACTION; 
INSERT INTO Media (MediaID) VALUES (22); 
SET CONSTRAINTS Idea_must_have_media DEFERRED; 
-- omit the above if the constraint was declared as INITIALLY DEFERRED. 
INSERT INTO Idea (IdeaID) VALUES (55); 
INSERT INTO IdeasMedia (MediaID, IdeaID) VALUES (55, 22); 
SET CONSTRAINTS Idea_must_have_media IMMEDIATE; 
-- above may be omitted: constraints are checked at commit anyhow. 
COMMIT TRANSACTION; 

可悲的是,SQL Server不支持CREATE ASSERTION也不CHECK約束可以參照其他表,也沒有延遲約束!

  • 創建「幫手」存儲的特效的添加,修改和刪除Ideas及其各自 IdeasMedia關係:

    就個人而言,我會在SQL Server如下處理這個問題。

  • 刪除表中的更新權限以強制用戶使用 procs。
  • 當刪除MediaIdea實體時,可能使用觸發器來處理場景。 1..1關係,而是:

當然,這(再次程序)實現遠基於集合的理想的方法,這或許可以解釋爲什麼大多數SQL程序員視而不見的需求爲1移除假設設計師意味着1:0..N!

+0

嘿onedaywhen謝謝你真的很棒的回答!您的答案非常廣泛,並描述了針對我的問題實現解決方案的不同方法。我真的很感激。即使如此,所有的解決方案都非常難看。我決定在我的業務邏輯中處理這個問題。而thx爲語法修正;) – MUG4N

1

您創建一個FK(外鍵) PK(主鍵)媒體。同時對FK應用約束條件NOT NULL

如果你已經在表中的數據,see here


舉例說明:

Media    Idea 
-----    ---- 
id | type   id | description  | media_id 
----+-----   ----+-------------------+---------- 
1 | TV    90 | advertise  | 2 
2 | Magazine  90 | advertise  | 1 
3 | Mail   91 | superbowl party | 1 
        91 | superbowl party | 3 

我並不是說這是偉大的設計,我絕對不知道你是什麼表正在存儲(由我的不好的例子表示),但這個想法不能存在w/o媒體條目鏈接到。沒有來回的鏈接,你要求1:N,而不是N:N,你可能想要。

想到表名時,好像你的想法倒退了。我想你會有1:媒體對N:想法而不是其他方式。


CREATE TABLE idea (
    id  integer 
    , media_id integer NOT NULL REFERENCES media 
) 

--or-- 

CREATE TABLE idea (
    id   integer 
    , media_id NOT NULL 
    , FOREIGN KEY (media_id) REFERENCES media 
); 

注:這不是標準化的,所以你需要第三個表以匹配聯接。

+1

所以這兩個表有彼此的外鍵?這可能會有點奇怪嗎?它也遭受Aleks G.指定的「雞和蛋」問題。 – David

+0

這意味着交叉引用...我聽說過交叉引用的壞消息。這是一種常見的最佳做法嗎?或者有這種情況的一些最佳實踐? – MUG4N

+0

@David你是什麼意思,你爲什麼要FK去海誓山盟,只有一個方法FK從想法到媒體 – vol7ron