eu tenho essas mesas
CREATE TABLE users
(
id INT NOT NULL AUTO_INCREMENT,
username VARCHAR(15) NOT NULL UNIQUE,
password VARCHAR(200) NOT NULL,
name VARCHAR(15) NOT NULL,
last_name VARCHAR(25) NOT NULL,
department VARCHAR(50) NOT NULL,
salary INT,
age TINYINT NOT NULL,
email VARCHAR(50),
enabled TINYINT NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE roles
(
id INT NOT NULL AUTO_INCREMENT,
role VARCHAR(15) NOT NULL UNIQUE,
PRIMARY KEY (id)
);
e também uma tabela de junção entre eles
CREATE TABLE user_role
(
user_id INT NOT NULL,
username VARCHAR(15) NOT NULL,
role_id INT NOT NULL,
role VARCHAR(15) NOT NULL,
PRIMARY KEY (user_id, role_id),
FOREIGN KEY (user_id) REFERENCES users (id),
FOREIGN KEY (role_id) REFERENCES roles (id)
);
Como posso preenchê-lo com uma instrução SQL?
Suponha que a users
tabela tenha esses valores (os id
s são gerados automaticamente)
VALUES ('mickey_m', '$2y$10$i5SJc2KAriHGn7Dz2rRQHuQ3JfBxlzMaPVKP1YdEJCukryDY9NbVC',
'Mickey', 'Mouse', 'sales', 180000, 95, 'mickey_m@gmail.com', 1),
('donald_d', '$2y$10$E6SHpAN0aZGQ43HAO.TPiO27kDKXOGIgDc8xWDJdl2Prn2wzQzz5y',
'Donald', 'Duck', 'information technology', 190000, 89, 'donald_d@outlook.com', 1),
('scrooge_m', '$2a$10$ycVpl2BSD6o19wa3xXtmrOxc8qZjwoIk.e3oZqgQBOE.3NHANAYqa',
'Scrooge', 'McDuck', 'board of directors', 700000, 76, 'scrooge@gmail.com', 1)
E suponha que eu queira que todos tenham um USER
papel e scrooge_m
também tenham um ADMIN
papel. A tabela de junção deve ser mais ou menos assim (mais id
s que talvez eu não saiba no momento de escrever a instrução SQL)
ID do usuário | nome de usuário | role_id | papel |
---|---|---|---|
mickey_m | DO UTILIZADOR | ||
donald_d | DO UTILIZADOR | ||
scrooge_m | DO UTILIZADOR | ||
scrooge_m | ADMINISTRADOR |
Minha tentativa aparentemente ruim está abaixo (não testei, mas parece errado – embora o IDE não destaque nada aqui). Eu costumava INSERT IGNORE
contar com a possibilidade de que as linhas já estivessem lá
INSERT IGNORE INTO user_role
WITH user_to_role(user, role) AS ( VALUES ROW('mickey_m', 'USER'),
ROW('donald_d', 'USER'),
ROW('scrooge_m', 'USER'),
ROW('scrooge_m', 'ADMIN')
SELECT users.id, users.username, roles.id, roles.role FROM users JOIN
roles ON users.username = user_to_role.user AND roles.role = user_to_role.role;
Quando eu executo no dbfiddle , recebo
Unknown column 'user_to_role.user' in 'on clause'
Se as únicas coisas forem
roles
o id e o papel, livre-se da tabela.Então, em vez de discutir uma tabela muitos-para-muitos, é simplesmente uma tabela 1:muitos:
Não inclua
username
nessa tabela; (ou seu originalroles
), é redundante. Em vez disso, use aJOIN
sempre que precisar de outras colunas.Ao inserir em uma tabela com um
AUTO_INCREMENT
, faça uma linha por vez para obter o id:Use
INSERT IGNORE
se for provável que você esteja reinserindo. UseUPDATE
ouINSERT ... ON DUPLICATE KEY UPDATE
para fazer alterações sem ou com a opção de também inserir.Isso parece funcionar:
Usar pseudônimos parece opcional (acredito que pseudônimos são sempre opcionais). Isso também funciona:
Você ainda está livre para postar sua própria solução.
O engraçado é que meus scripts não parecem alterar as propriedades
NOT NULL
ouUNIQUE
das minhas colunas. Mas isso provavelmente tem a ver com o meuapplication.properties
e não está mais no tópico. - Serguei