在SQL Server中创建通用表

时间:2015-02-04 09:57:51

标签: sql-server database-design

我们有一个使用SQL Server 2012作为数据库的客户端 - 服务器系统。系统会定期更新和增强。

我们最近意识到我们有一个重复的表设计模式:一个表,它将Users表链接到数据库中的其他表,形成了视图和权限的基础。示例:

CREATE TABLE Documents_Users (
    ID int not null identity(1,1) not for replication,
    UserID int not null, -- foreign key to the Users table
    DocumentID int not null, --- foreign key to the Documents table
    [...]
)

我们在想,不是创建所有这些表,而是创建一个这样的大表:

CREATE TABLE UserPermissions (
    ID int not null identity(1,1) not for replication,
    UserID int not null, -- foreign key to the Users table
    ObjectID int not null, -- pointer to any object ID in another table
    TableID int not null, -- actual id of the referenced table in sys.objects
    [...]
)

优点:一个表解决了所有当前和未来表的所有权限需求。

缺点:

  1. 没有外键。我们将不得不创建一个偶尔运行的作业并删除孤立指针(如果我们不在存储过程中删除它们)。

  2. 视图需要按照

    的方式进行查询

    从[some_table]中选择*,其中ID为(     从UserPermissions中选择ObjectID,其中TableID = object_id(' someTableName') )

  3. 创造像这样的概括是否值得,并且是一种好的做法?有一个表和一个索引可以读取,而不是可能有很多不同的表吗?

3 个答案:

答案 0 :(得分:2)

我的直觉是,这可能不是一个好主意。

更好的选择是使用继承 1

  • 将用户连接到基表,
  • 然后"继承"基表中的其他表。 2

您添加的任何未来表,您只需从现有基表继承,它们将自动插入"你已经实施的安全逻辑。

对于它的价值,我们目前正在这样的架构之上实现一个相当强大的安全机制,到目前为止它运作良好。


1 在ER建模中也称为:"类别"或者"泛化层次"或"继承"等

2 不幸的是,今天的关系数据库并没有直接支持继承(甚至PostgreSQL都没有,只能部分实现它),所以你需要模拟它(这里是one example并且您可能还想阅读this),这会带来自身的问题,但在某些情况下仍然非常有用。

答案 1 :(得分:0)

我现在面临同样的选择,我想我会选择通用解决方案。我不是泛型解决方案的粉丝,因为语义不太明显,在你知道它之前,你处在一个难以理解的混乱中。但我倾向于认为它是允许的,如果它服务于域范围,明确定义的目的,例如日志,语言等,安全性。

对于反对意见,我认为删除的孤儿不会妨碍任何事情,所以偶尔清理一次就是一个很好的解决方案。 至于查询,我将创建一个内联表值函数,也就是将UserId作为参数的参数化视图(而不是每个表的视图)。可以选择性地限制表本身的读取权限,并且只允许对视图的权限。

我认为性能提升是微不足道的,但通用解决方案仍然会更好;我的主要原因是图表不那么杂乱。

答案 2 :(得分:0)

我不会这样做,因为当用户到X权限需要基于X的类型的属性时会发生什么。即UserDocumentPermission可能具有读取,写入,删除,添加等,而UserCarPermission可能具有驱动,启动和停放权限。

谁在乎你是否有很多牌桌。您只需使用命名约定即可轻松记住。