0

我为基于角色的访问控制设置了四个基本表:

CREATE TABLE roles (
  role_id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  role_name VARCHAR(20) NOT NULL,
  valid ENUM('Y','N') DEFAULT 'Y',

  PRIMARY KEY (role_id)
);
CREATE TABLE permissions (
  perm_id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  perm_desc VARCHAR(20) NOT NULL,
  valid ENUM('Y','N') DEFAULT 'Y',

  PRIMARY KEY (perm_id)
);
CREATE TABLE role_perm (
  role_id INTEGER UNSIGNED NOT NULL,
  perm_id INTEGER UNSIGNED NOT NULL,
  valid ENUM('Y','N') DEFAULT 'Y',

  FOREIGN KEY (role_id)
    REFERENCES roles(role_id),
  FOREIGN KEY (perm_id)
    REFERENCES permissions(perm_id)
);
CREATE TABLE user_role (
  user_id VARCHAR(20) NOT NULL,
  role_id INTEGER UNSIGNED NOT NULL,
  valid ENUM('Y','N') DEFAULT 'Y',

  FOREIGN KEY (user_id)
    REFERENCES users(user_id),
  FOREIGN KEY (role_id)
    REFERENCES roles(role_id)
);

现在说我想删除一个特定的角色以及与它的所有关联。我可以分别进行每个查询:

$sql = "UPDATE roles
        SET valid = 'N'
        WHERE role_id = :role_id";

$sql2 = "UPDATE user_role
         SET valid = 'N'
         WHERE role_id = :role_id";

$sql3 = "UPDATE role_perm
         SET valid = 'N'
         WHERE role_id = :role_id";

此代码仅在找到时才会执行第一个查询role_id,对于其他查询也是如此。

我想知道是否可以将所有三个查询合并到一个语句中,结果完全相同,例如(我认为这行不通):

$sql = "UPDATE roles, user_role, role_perm
        SET roles.valid = 'N', user_role.valid = 'N', role_perm.valid = 'N'
        WHERE roles.role_id = :role_id AND user_role.role_id = :role_id AND role_perm.role_id = :role_id";

或者,将查询分开/使用某种类型的 JOIN 会更好吗?

4

2 回答 2

1

虽然以下内容在 MySQL 中有效,但我怀疑您真的想扩展您的 FOREIGN KEY 引用并阅读 ON UPDATE CASCADE ...

UPDATE roles r 
  JOIN user_role ur
    ON ur.role_id = r.role_id
  JOIN role_perm rp
    ON rp.role_id = r.role_id
   SET r.valid = 'N'
     , ur.valid = 'N'
     , rp.valid = 'N';
于 2013-05-11T15:13:08.880 回答
0

您显然没有测试的最后一个查询应该可以正常工作。

作为旁注:我认为有比枚举更好的选择来表示布尔值('Y'/'N')。您可以通读这个主题,看看哪个对您有好处:Which mysql datatype to use for storage boolean values

于 2013-05-11T14:49:47.913 回答