LINUX.ORG.RU

Связь many-to-many

 ,


0

1

Всем привет, возникла задачка (она на c++, но под капотом MySQL). Необходимо реализовать такую модель:

- В базе должны быть как минимум таблицы: Users, Roles, Songs, Playlists, ... остальное на мое усмотрение.

- Юзеры имеют одну из ролей: Admin (имеет доступ ко всем фичам), free user имеет ограничение на 1 playlist и 10 песен в нем, и paying user может имеет неограничеченное количество плейлистов и ограничение до 1000 песен в плейлисте

- Ну и понятно, что одна песня может быть в нескольких плейлистах

Дело в том, что я C++ программист, но с базами данных дела не имел и про SQL знаю примерно ничего.

Помогите это организовать, ткните, что почитать.


Помогите это организовать

Чтобы сделать связь, надо из одной таблицы ссылаться на другую. Чаще всего в таблице A заводят столбец (комбинацию столбцов), в котором хранятся данные, уникально идентифицирующие какую-нибудь запись из таблицы B; при этом на этот столбец (комбинацию столбцов) обычно накладывают ограничение внешнего ключаforeign key constraint.

Т.е., например, у нас есть таблицы Roles с суррогатным первичным ключём (surrogate primary key) id, в котором хранятся идентификаторы ролей (ключи ещё могут быть натуральными, но это сейчас не важно):

idname
1admin
2free user
3paying user

В таблице Users тогда заводим столбец role_id, в котором для каждой записи пользователя хранится идентификатор его роли:

idfull_namerole_id
1Вася Пупкин3
2Иван Иванов1

Т.е. у пользователя Вася Пупкин роль paying user, у Ивана Иванова — admin.

(Если ты на 100% уверен, что с ролями не будут связаны никакие дополнительные данные, то можно вообще обойтись без отдельной таблицы для ролей, а вместо этого обойтись ENUM-ами — не знаю, правда, поддерживает ли их MySQL.)

Чтобы организовать связь many-to-many, тебе понадобится т.н. таблица связи (join table). Это по сути обычная таблица, только в ней записи ссылаются сразу на несколько других таблиц. Например, в твоём случае имеет смысл иметь таблицу связи PlaylistSongs, в которой будут одновременно ссылки и на записи из таблицы Playlists, и на записи из таблицы Songs.

ткните, что почитать

Рекомендую почитать мануал PostgreSQL, очень понятно всё расписано.

theNamelessOne ★★★★★
()
Последнее исправление: theNamelessOne (всего исправлений: 1)
Ответ на: комментарий от MKuznetsov

Ну не имел я за 14 лет опыта работы с C++ опыта работы с БД. Такое бывает.

Benis
() автор топика
Ответ на: комментарий от Ford_Focus

Спасибо, я подобный совет нашел на стековерфлоу, но это лишь подтверждает, что твой совет верный.

Benis
() автор топика

Всем привет, возникла задачка (она на c++, но под капотом MySQL).

На Lazarus и Firebird будет быстрее и понятнее.

iZEN ★★★★★
()
Ответ на: комментарий от Twissel

Я бы сказал, что довольно далёк, я не старался как-то этот вопрос разобрать.

theNamelessOne ★★★★★
()
Ответ на: комментарий от theNamelessOne

Если ты на 100% уверен, что с ролями не будут связаны никакие дополнительные данные

Это тут ключевое. Но, если у роли должны быть разрешения на доступ к ресурсам, тогда только полноценный RBAC

IMHO

Twissel ★★★★★
()
Последнее исправление: Twissel (всего исправлений: 2)

ткните, что почитать

Любой учебник по базам данных для пту.

crutch_master ★★★★★
()

User: id, name, password_hash, ...
Role : id, name, ...
UserRole : id, id_user, ...
Songs : id, name, ...
Playlist : id, id_user, name, ...
PlaylistSong : id, id_playlist, id_song, ...
К каждой таблице добавить actual, date_ins, date_upd по вкусу.
Связь много-много не нужна (а если и нужна, то я не хз, куда вы её хотите впихнуть и зачем)

crutch_master ★★★★★
()
Последнее исправление: crutch_master (всего исправлений: 1)
2 сентября 2021 г.

Там должна быть таблица типа Actions либо отдельным полем в Roles хранить список действий как массив (JSON, ARRAY) либо в виде comma-separated строки. Например:

~/work/docker-stack 
➜ docker-compose exec postgres psql -U docker             
psql (13.4)
Type "help" for help.
                                                                                                          
docker=# create table roles(id serial not null primary key, name varchar(31) unique, actions text[]);
CREATE TABLE
docker=# insert into roles (name, actions) values ('Petuh', ARRAY['love_rust', 'suck_cocks']);
INSERT 0 1
docker=# select * from roles;
 id | name  |        actions         
----+-------+------------------------
  1 | Petuh | {love_rust,suck_cocks}
(1 row)

docker=#

А у юзера уже role_id будет… Как там в моем SQL я уже не помню. И хз что ты имеешь в виду MariaDB или Percona. Меня бы насторожило, что используется никому ненужная MySQL…

А дальше тригееры всякие создаешь, в них проверяешь роли, можно ли песню послухать и тп

tz4678 ★★
()
Последнее исправление: tz4678 (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.