2017-10-18 178 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及其基于函数的索引 –

相关问题