【问题标题】:Adding default configurations for many-to-many tables为多对多表添加默认配置
【发布时间】:2018-09-14 18:18:19
【问题描述】:

这里是 MySQL。我有以下users 表:

describe users;
+----------------------------------+---------------------+------+-----+---------+----------------+
| Field                            | Type                | Null | Key | Default | Extra          |
+----------------------------------+---------------------+------+-----+---------+----------------+
| user_id                          | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| user_status_id                   | bigint(20) unsigned | NO   | MUL | NULL    |                |
| profile_id                       | bigint(20) unsigned | YES  | MUL | NULL    |                |
+----------------------------------+---------------------+------+-----+---------+----------------+

我想添加一个简单的 RBAC 模型,其中:

  • 用户可以拥有 0+ 个角色
  • 角色有 0+ 个权限

我建议的表结构:

[roles] table
---
role_id : BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT
role_name : VARCHAR(50)

[permissions] table
---
permission_id : BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT
permission_name : VARCHAR(50)

[roles_x_permissions] many:many table
---
roles_x_permissions_id : BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT
role_id : BIGINT UNSIGNED FOREIGN KEY to [roles] table
permission_id : BIGINT UNSIGNED FOREIGN KEY to [permissions] table

[users_x_roles] many:many table
---
users_x_roles_id : BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT
user_id : BIGINT UNSIGNED FOREIGN KEY to [users] table
role_id : BIGINT UNSIGNED FOREIGN KEY to [roles] table

以及应用将支持的实际角色和权限(至少最初是这样):

INSERT INTO permissions (
  permission_name
) VALUES (
  'CanDoSomeBasicStuff'
);

INSERT INTO roles (
  role_name
) VALUES (
  'BasicUser'
);

INSERT INTO roles_x_permissions (
  role_id,
  permission_id
) VALUES (
  1,    // BasicUser
  1     // CanDoSomeBasicStuff
);

INSERT INTO users_x_roles (
  user_id,
  role_id
) VALUES (
  ???
);

我苦苦挣扎的地方是:默认情况下,所有现有用户都将拥有BasicUser 角色。我需要一种优雅的方式在单个命令中将所有现有用户分配给这个 BasicUser 角色,但我无法确定 SQL 命令的外观:

INSERT INTO users_x_roles uxr (
  user_id,
  role_id
) VALUES (
  ???,   # How to do this for each user record in the users table?
  ???    # How to fetch the correct role_id for the BasicUser role?
)

你知道这个 SQL 命令是什么样子的吗?

【问题讨论】:

    标签: mysql sql many-to-many ansi-sql


    【解决方案1】:

    INSERT ... VALUES 语法插入一条记录。你需要使用INSERT ... SELECT 语法,像这样:

    INSERT INTO users_x_roles (
      user_id,
      role_id
    )
     SELECT 
      user_id, 
      (SELECT MAX(role_id) FROM roles where role_name='BasicUser')
     FROM users;
    

    或者,如果您不喜欢子查询:

    INSERT INTO users_x_roles (
      user_id,
      role_id
    )
     SELECT 
      u.user_id, 
      r.role_id 
     FROM users u CROSS JOIN roles r where r.role_name='BasicUser';
    

    更新:错字出现在 INSERT 语句中。我复制了您的代码并使用了如下语法:INSERT INTO users_x_roles uxr,这是无效的:您不能在 Insert Into 子句中使用别名。

    现在一切正常。检查SQL Fiddle

    【讨论】:

    • 实际上@cha 你的两个 SQL 语句都会产生语法错误。我确实更喜欢第二个选项(使用交叉连接)但是我收到了ERROR 1064 (42000): You have an error in your SQL syntax 错误。有什么想法吗?
    • 很难判断是什么导致了错误。您的错误描述性不够。你能为你的模式制作一个 sqlfiddle 以便我们试用吗?
    • 没问题! Here you go! -- 再次非常感谢!!! 小修改:实际上我的users 表称为accounts(所有用户都有一个帐户)。
    【解决方案2】:

    如何对用户表中的每条用户记录执行此操作?

    编写一个只选择一个用户的查询,例如:

    SELECT user_id FROM users WHERE name = 'John'
    

    如何获取 BasicUser 角色的正确 role_id?

    编写一个查询来准确选择一个所需的角色,例如:

    SELECT role_id FROM roles WHERE role_name='BasicUser'
    

    最后以这种方式将这两个查询放入INSERT语句中(使用括号):

    INSERT INTO users_x_roles uxr (
      user_id,
      role_id
    ) VALUES (
      ( SELECT user_id FROM users WHERE name = 'John' ) ,
      ( SELECT role_id FROM roles WHERE role_name='BasicUser' )
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-26
      • 1970-01-01
      • 2015-10-27
      • 1970-01-01
      • 1970-01-01
      • 2013-09-09
      • 1970-01-01
      相关资源
      最近更新 更多