2016-05-13 19 views
0

我有一個程序,用戶可以創建和編輯任務。每個任務可以分配給它的0-n 問題插入到表中 - 放棄重複鍵,其中鍵可以爲空

當用戶正在編輯任務時,他們會看到一個問題列表(以前創建),他們可以(1)刪除或(2)編輯。他們還可以(3)在問題列表中添加一個新問題。

每個問題都必須與每個指定成員有關係,以便可以跟蹤他們的進度。這在task_data_table完成。

task_data_table 
============================================================================ 
| Field    | Type   | Null | Key | Default | Extra   | 
============================================================================ 
| id    | int(11)  | no | PRI | Null | auto_increment | 
| completion_date | timestamp | yes |  |   |    | 
| answer   | varchar(255) | yes |  |   |    | 
| task_id   | int(11)  | yes | MUL |   |    | 
| question_id  | int(11)  | yes | MUL |   |    | 
| member_id   | int(11)  | yes | MUL |   |    | 
---------------------------------------------------------------------------- 

表的內容可能是這樣的:

========================================================================= 
| id | completion_date  | answer | task_id | question_id | member_id | 
========================================================================= 
| 1 | 2016-05-13 11:00:00 | NULL | 20  | NULL  | 2   | 
| 2 | 2016-05-13 11:00:00 | yes | 20  | 8   | 2   | 
| 3 | 2016-05-13 11:00:00 | no  | 20  | 9   | 2   | 
------------------------------------------------------------------------- 

上面的第一個條目question_id等於NULL,因爲它是用於任務作爲一個整體,而其他特定題。另外,每個問題對於一項任務都是獨一無二的


我試圖通過減少循環和提交更改時對數據庫做不必要的檢查量,以優化一些後端邏輯和查詢時間。我嘗試這樣做的一種方法是將task_idquestion_id一起使用UNIQUE密鑰,以便在執行INSERT INTO之前,如果所述成員和問題的task_data已經存在,則我不必對數據庫進行檢查。所以我做:

ALTER TABLE task_data_table ADD UNIQUE unique_index (question_id, student_member_id); 

不過,我剛剛從文檔中發現了:

UNIQUE索引允許,它可以包含NULL列的多個NULL值

我已經看了成爲解決這個問題的方法,但我只找到使用0作爲默認值的建議,而不是NULL。不幸的是,這是不可能的,因爲task_idquestion_id都是外鍵。

我嘗試了一些查詢,我發現IF NOT EXISTSNOT IN,但他們沒有奏效。我將如何去解決這個問題?

+0

在MySQL中,我認爲這個功能需要一個觸發器。 –

+0

@GordonLinoff,嗯......你能解釋這個觸發器是如何工作/做的嗎? – Chris

回答

1

其他數據庫有更好的機制。在MySQL中,最好的解決方案可能是向questions添加一個虛假的行。

此行的ID應爲0或-1。然後,您可以使用外鍵約束和唯一約束來獲得所需的行爲。

如果您要取決於列中的NULL值,則您需要小心。解決此問題的方法是使用一個觀點:

create view v_task_data_table as 
    select . . ., 
      (case when question_id = -1 then NULL else question_id end) as question_id 
    from task_data_table; 

然後,希望NULL值將通過查看有沒有它的任何代碼。

+0

這真的很不幸。有一個虛假的行確實存在於我的腦海裏,但它確實看起來像是一種潛在的危險方法。確定的反模式。回到繪圖板我猜。 – Chris

+0

@Chris。 。 。其他數據庫支持篩選索引和計算列,這也可以幫助實現這一想法。實際上,MySQL支持最新版本中的計算列,因此最新版本中可能會有解決方案。 –