基于用户角色权限的数据库设计

时间:2017-09-02 21:39:48

标签: sql database oracle database-design

我想为Java Web应用设计数据库,其中用户可以具有特定的角色角色可以拥有权限根据 PERMISSION_CODE

访问特定标签

所以,我创建了三个表,如:

 CREATE TABLE "PAWAN"."USERS_TABLE" 
    (   
    "ID" NUMBER(4,0) NOT NULL ENABLE, 
    "USER_NAME" VARCHAR2(20 BYTE) NOT NULL ENABLE, 
    "PASSWORD" VARCHAR2(100 BYTE) NOT NULL ENABLE, 
    "FIRST_NAME" VARCHAR2(20 BYTE) NOT NULL ENABLE, 
    "LAST_NAME" VARCHAR2(20 BYTE), 
    "CREATED_DATE" DATE DEFAULT sysdate, 
    "ROLE_ID_FK" NUMBER(4,0) NOT NULL ENABLE, 
    PRIMARY KEY ("ID") ENABLE,
    CONSTRAINT "FK_ROLE_ID" FOREIGN KEY ("ROLE_ID_FK")
    REFERENCES "PAWAN"."USER_ROLES" ("ID") ENABLE
    );     

  CREATE TABLE "PAWAN"."USER_ROLES" 
    (   
    "ID" NUMBER(4,0) NOT NULL ENABLE, 
    "ROLE_TYPE" VARCHAR2(20 BYTE) NOT NULL ENABLE, 
    "ROLE_DESCRIPTION" VARCHAR2(100 BYTE) NOT NULL ENABLE, 
    "CREATED_DATE" DATE DEFAULT sysdate, 
    "PERMISSION_ID_FK" NUMBER(4,0) NOT NULL ENABLE, 
    PRIMARY KEY ("ID") ENABLE, 
    CONSTRAINT "PERMISSION_ID" FOREIGN KEY ("PERMISSION_ID_FK")
    REFERENCES "PAWAN"."PERMISSIONS_TABLES" ("ID") ENABLE
    );   


CREATE TABLE "PAWAN"."PERMISSIONS_TABLE" 
   (    
    "ID" NUMBER(4,0) NOT NULL ENABLE, 
    "PERMISSION_CODE" VARCHAR2(20 BYTE) NOT NULL ENABLE, 
    "PERMISSION_DESC" VARCHAR2(100 BYTE) NOT NULL ENABLE, 
    "CREATED_DATE" DATE DEFAULT sysdate, 
     PRIMARY KEY ("ID") ENABLE
   );

现在,我需要第四个表,其中包含属于 PERMISSION_CODE PERMISSIONS_TABLE

的标签列表

我脑子里想到的是有一个像

这样的列的表格
  • PERMISSION_CODE
  • TAB1(是/否)
  • TAB2(是/否)等等..

但这不是一个好设计,因为每次创建一个新标签时,我都要添加一个列。 一种替代方案是具有如下结构:

  • PERMISSION_CODE
  • TAB_NAME

但这种方式没有。行会更多。

有没有办法将标签存储在类似结构的数组中?任何人都可以建议我采取更好的方法吗?

1 个答案:

答案 0 :(得分:1)

  

但这种方式没有。行将更多。

数据库很好地管理了大量的行,数百万行不是问题。

  

有没有办法将标签存储在类似结构的数组中?

不不不 - 不要这样做。
这打破了Database normalization规则,特别是first normal form表示:

  

第一范式(1NF)是关系中关系的属性   数据库。当且仅当域时,关系是第一范式   每个属性仅包含原子(不可分割)值,以及   每个属性的值仅包含该域中的单个值

这种方法(在一个列中存储许多值)乍一看似乎很有吸引力,但有一天当有人要求您提出查询时,您将陷入混乱状态“给我所有有权访问标签的用户TAB-233 ”。
这种方法的其他一些缺点:

  1. 每个查询都必须解析数组
  2. RDBMS无法在多值列上使用索引,每个查询(如SELECT ... WHERE tab='TAB-333')必须始终使用全表扫描,并且不可扩展。
  3. 如何更新或删除?每个更新命令都必须解压缩数组,更改/删除一个值并打包并将更改后的数组存储回列中,而不是简单的UPDATE ... WHEREDELETE .. WHERE ...
  4. 您不能在此列上使用任何参照完整性。
  5. 有关详细信息,请参阅this question的aswer。

    在您的模型中,存在以下关系:

    1. 用户角色
    2. 角色权限代码
    3. 权限代码标签
    4. 但是有n:n关系,而不是1:n,因为我可以看到:

      1. 角色许多用户(因为多个用户可以拥有相同的角色)
      2. 权限代码具有多个角色(因为多个角色可以拥有相同的权限代码)
      3. 标签许多权限代码(因为多个权限代码可以使用相同的标签)
      4. 所以在这个模型中会有以下表格:

        • USERS(id,user_name,password等)
        • ROLES(id,role_name等)
        • PERMISSION_CODES(id,code_name等)
        • TABS(id,tab_name等)
        • USER_ROLES(user_id,role_id)
        • ROLE_PERMISSIONS(user_id,perrmission_id)
        • PERMISSION_TABS(permission_id,tb_id)