2017-10-18 130 views
1

我有一個應用程序,用戶可以在其中創建自己的自定義私人標籤,但也有一些固定的系統範圍的通用標籤。標籤存儲在數據庫表中,其中通用標籤是USER_IDNULL的那些標籤。爲包括全局用戶在內的每個用戶實施獨特價值

CREATE TABLE TAG (
    TAG_ID INT IDENTITY(1, 1) NOT NULL, 
    TAG_NAME VARCHAR(40) NOT NULL, 
    USER_ID INT, 

    CONSTRAINT TAG_PK PRIMARY KEY (TAG_ID), 

    CONSTRAINT TAG_FK1 FOREIGN KEY (USER_ID) 
    REFERENCES [USER] (USER_ID) 
); 
CREATE INDEX TAG_IDX1 ON TAG (USER_ID); 

我想在數據庫級別的標籤是唯一的每個用戶強制執行,是什麼意思是說:

  • 用戶可能僅具有給出名稱的標籤,但其他客戶也可以有他們自己的標籤這樣的名字。

  • 常見標籤也應該計算在內,因此用戶不能創建已經很常見的標籤。

這樣一個簡單的索引將無法正常工作,因爲它只能防止羣體中受騙者(普通標籤的每個用戶) - 它仍然有可能作爲用戶標籤重新創建常用標記:

CREATE UNIQUE INDEX TAG_UK1 ON TAG (TAG_NAME, USER_ID); 

我相信,SQL Server不允許在索引表達式,如:

-- Incorrect syntax near the keyword 'COALESCE'. 
CREATE UNIQUE INDEX TAG_UK1 ON TAG (TAG_NAME, COALESCE(USER_ID, 'COMMON')); 

你能想出一些其他的辦法?

+1

聽起來像你需要重新考慮一下架構。這是一種多對多的關係(有一些額外的注意事項),幾乎不可能只用兩個表。 –

+0

在這種情況下,通過索引保證唯一性可能無法實現-AFAIK,無論如何,聽起來你也會因爲性能原因利用索引。你爲什麼不把這個檢查放在存儲過程或觸發器中? – Icarus

+0

@SeanLange我沒有這樣想過,從數據庫設計的角度來看是有道理的。但考慮到我可能還需要編輯管理工具和代碼庫的許多其他部分,也許最好是允許模糊並調整UI以單獨顯示它們 - 這對我的精確用例可能是可以接受的。 –

回答

0

可能需要處理這與trigggers。

如果您插入或更新新的全局標籤,則在標籤表中。您需要檢查每個用戶,看他是否已經擁有該標籤並將其轉換爲全局標籤

例如,您有Angular作爲標籤,但某些用戶是頭部並創建了Angular4。當Angular4成爲全局標籤時,您需要將其從所有用戶中刪除。

同樣爲用戶創建標籤,您可以檢查全球是否已經有該標籤並引發錯誤。

+0

通用標籤在初始數據集中是硬編碼的,它們不能更改。 –

+1

不改變我的答案。爲用戶添加標籤只能使用觸發器進行驗證 –

+0

謝謝。當我想出這個輝煌的設計xD時,我可能會考慮Oracle及其基於函數的索引 –

相關問題