PostgreSQL - 如何识别数据库中用户的三个角色?

时间:2016-02-05 16:02:18

标签: sql database postgresql database-design

我正在构建一个需要三种用户角色的数据库架构:普通用户,管理员和超级管理员。我的第一种方法是创建两个表,一个用于普通用户,另一个用于继承自users表的admin和super admin。所以表定义是这样的:

CREATE TABLE users (
  id BIGSERIAL NOT NULL PRIMARY KEY,
  email TEXT NOT NULL UNIQUE,
  password TEXT NOT NULL,
  name TEXT NOT NULL,
  gender CHAR NOT NULL,
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE admins (
  phone BIGINT NOT NULL,
  doc BIGINT NOT NULL,
  super_admin BOOLEAN NOT NULL,
  id BIGINT NOT NULL PRIMARY KEY REFERENCES users(id)
);

但我不确定如何在需要时选择用户或管理员。所以现在我想是否只留下一个用户"表并定义一个新表"角色"用户将匹配的位置,以便使用列" role"指定用户是普通用户,管理员还是超级用户。

3 个答案:

答案 0 :(得分:0)

首先,您不应该将电话号码存储为整数。你应该使用字符串。世界上存在的有效电话号码可以以0开头,整数无法处理。

这可能很复杂。首先,我注意到admin和supers有两个额外的数据字段。如果您将数据包含在users表格中,那么有权访问users的任何人都会获得此信息。通常,这很好。但是,我可以想象这是一个问题。

Postgres直接支持表继承(参见here),因此您不需要显式的外键关系。继承是处理派生用户类型的好方法。它为您提供了adminssupers的替代表格,您可以在from子句中引用这些表格(这些也可供用户使用)。

有两种选择。一种是将附加列(phonedoc)放在users表中,以及类型的指示符。这可以是单个字段("正常","管理员","超级")或三个标志(" IsNormal"," ; IsAdmin"和" IsSuper")。另一种方法是使用单独的UserRoles联结表。

这些方法中的每一种都有其优点。因为你已经开始了多个表的路径并且你有管理员和超级的增强数据,我可能会建议继承这个特定的情况。请注意,语法可能是:

CREATE TABLE admins (
  phone BIGINT NOT NULL,
  doc BIGINT NOT NULL
) inherits (users);

CREATE TABLE supers (
  phone BIGINT NOT NULL,
  doc BIGINT NOT NULL
) inherits (users);

答案 1 :(得分:0)

这可以通过引入两个新表来轻松解决:

  1. 角色 - 这将包含所有类型的角色
  2. user_roles-用于映射具有角色的用户。
  3. 示例数据:

     Roles
     -------------------
     |ID |role_type   | 
     -------------------
     |1 |Admin        |
     |2 |Normal       |
     |3 |Super Admin  |
     -------------------
    
     user_roles
     ------------------
     |user_id |role_id|
     ------------------
     |1      |1       |
     |1      |2       |
     |2      |3       |
     ------------------
    

    user_roles表格将FK referenceusersroles表格相对应。

答案 2 :(得分:0)

您可以在标量子查询中使用exists(),它会产生一个布尔表达式:

INSERT INTO users(email,name,password,gender) VALUES
        ( 'john@world', 'John' , 'John', 'S' ),
        ( 'mary@world', 'mary' , 'mary', 'S' ),
        ( 'Jeff@world', 'Jeff' , 'Jeff', 'J' ) ;

INSERT INTO admins(phone, doc, super_admin, id) VALUES
        ( '007' , 0, False, 2),
        ( '008' , 0, True, 3) ;

SELECT email,name,gender
        , (EXISTS (SELECT 1 FROM admins a WHERE a.id = u.id)) AS is_admin
        , (EXISTS (SELECT 1 FROM admins a WHERE a.id = u.id AND a.super_admin)) AS is_super_admin
FROM users u
        ;             

结果:

CREATE TABLE
INSERT 0 3
CREATE TABLE
INSERT 0 2
   email    | name | gender | is_admin | is_super_admin 
------------+------+--------+----------+----------------
 john@world | John | S      | f        | f
 mary@world | mary | S      | t        | f
 Jeff@world | Jeff | J      | t        | t

请注意:原始数据模型可能不完美,但查询至少可以解决手头的问题。 (你可以隐藏它 - 例如*在一个或两个视图中)