Добавление конфигураций по умолчанию для таблиц "многие ко многим"
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?
2 ответа:
Синтаксис
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
Как это сделать для каждой записи Пользователя в таблице users?
Напишите запрос, который выберет ровно одного пользователя, например:
SELECT user_id FROM users WHERE name = 'John'
Как получить правильный role_id для роли BasicUser?
Напишите запрос, который выберет ровно одну желаемую роль, например:
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' ) )