mysql view users vs admin users syntax inquiry - mysql

Setting up JDBC security realm with Glassfish and I came across this link that provides user control access (admin vs view users). here is the link for this tutorial.
http://jugojava.blogspot.com.eg/2011/02/jdbc-security-realm-with-glassfish-and.html?showComment=1459000091065#c232448315667617784
Few things I didn't understand in the guide and I hope if you can help. What do the lines below mean? (full sql code at the end of of the question)
KEY `fk_users_has_groups_groups1` (`group_id`),
KEY `fk_users_has_groups_users` (`user_id`),
I don't see any table named u but the code is using u.*. The code at the very bottom doesn't have "u" table in it. However, I see the reference to "u" in the inner Join. Can I do select u. based on this INNER JOIN?
CREATE VIEW `v_user_role` AS
SELECT u.username, u.password, g.group_name
FROM `user_groups` ug
INNER JOIN `users` u ON u.user_id = ug.user_id
INNER JOIN `groups` g ON g.group_id = ug.group_id;
Here is the full Code
CREATE TABLE `groups` (
`group_id` int(10) NOT NULL,
`group_name` varchar(20) NOT NULL,
`group_desc` varchar(200) DEFAULT NULL,
PRIMARY KEY (`group_id`)
);
CREATE TABLE `users` (
`user_id` int(10) NOT NULL AUTO_INCREMENT,
`username` varchar(10) NOT NULL,
`first_name` varchar(20) DEFAULT NULL,
`middle_name` varchar(20) DEFAULT NULL,
`last_name` varchar(20) DEFAULT NULL,
`password` char(32) NOT NULL,
PRIMARY KEY (`user_id`)
);
CREATE TABLE `user_groups` (
`user_id` int(10) NOT NULL,
`group_id` int(10) NOT NULL,
PRIMARY KEY (`user_id`,`group_id`),
KEY `fk_users_has_groups_groups1` (`group_id`),
KEY `fk_users_has_groups_users` (`user_id`),
CONSTRAINT `fk_groups` FOREIGN KEY (`group_id`) REFERENCES `groups` (`group_id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `fk_users` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
);
CREATE VIEW `v_user_role` AS
SELECT u.username, u.password, g.group_name
FROM `user_groups` ug
INNER JOIN `users` u ON u.user_id = ug.user_id
INNER JOIN `groups` g ON g.group_id = ug.group_id;
INSERT INTO `groups`(`group_id`,`group_name`,`group_desc`) VALUES
(1,'USER','Regular users'),
(2,'ADMIN','Administration users');
INSERT INTO `users`(`user_id`,`username`,`first_name`,`middle_name`,`last_name`,`password`) VALUES
(1,'john','John',NULL,'Doe','6e0b7076126a29d5dfcbd54835387b7b'), /*john123*/
(2,'admin',NULL,NULL,NULL,'21232f297a57a5a743894a0e4a801fc3'); /*admin*/
INSERT INTO `user_groups`(`user_id`,`group_id`) VALUES (1,1),(2,1),(2,2);

1) KEY indicates that those fields are indexed. The index is not unique. See create index documentation.
2) The "u" is an alias, specifically it is a table alias. You can use aliases to refer to a table or field name under a different name. An alias is specific to a query. The alias is defined in the from clause:
`users` u

Related

How to SELECT with the given tables?

CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(16) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `permissions` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`description` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `user_permissions` (
`user_id` int(11) DEFAULT NULL,
`permission_id` int(11) DEFAULT NULL,
KEY `user_id_fk` (`user_id`),
KEY `permission_id_fk` (`permission_id`),
CONSTRAINT `permission_id_fk` FOREIGN KEY (`permission_id`) REFERENCES `permissions` (`id`),
CONSTRAINT `user_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
);
Given the above tables, how can I perform a SELECT that will return <users.name> | <true / false> if a specific user.id has permissions.id 1, 2, 3 and 4 based on the user_permissions n:m table?
Something like:
SELECT users.name, (..something..) as valid FROM user_permissions WHERE users.id 1 has 1,2,3 and 4 permissions
You need a left join of users to user_permissions, group by user and conditional aggregation:
select
u.id, u.name,
case count(up.permission_id)
when 4 then 'true'
else 'false'
end result
from users u left join user_permissions up
on up.user_id = u.id and up.permission_id in (1, 2, 3, 4)
group by u.id, u.name

Create view with two reference to the same table

I have two tables
CREATE TABLE `persons` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`first_name` varchar(45) NOT NULL,
`last_name` varchar(45) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
CREATE TABLE `marriage` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`place` varchar(45) DEFAULT NULL,
`spouse1` int(11) NOT NULL,
`spouse2` int(11) NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `sp1` FOREIGN KEY (`id`) REFERENCES `persons` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `sp2` FOREIGN KEY (`id`) REFERENCES `persons` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
Now I would like to create the view with place of marriage and full names of both spouse. How can I do it? I tried like this (obviously not correctly):
CREATE
ALGORITHM = UNDEFINED
DEFINER = `root`#`localhost`
SQL SECURITY DEFINER
VIEW `mar` AS
select
`marriage`.`place` AS `place`,
`persons`.`first_name` AS `first_name_sp1`,
`persons`.`first_name` AS `first_name_sp2`
from
(`persons`
join `marriage`)
where
((`marriage`.`spouse1` = `persons`.`id`)
and (`marriage`.`spouse2` = `persons`.`id`))
The select that you want needs to mention persons twice:
select m.place, p1.first_name as first_name_sp1,
p2.first_name as first_name_sp2
from marriage m join
persons p1
on m.spouse1 = p1.id join
persons p2
on m.spouse2 = p2.id;
You can put this in a view just by putting create view mar as before it.
And note the use of table aliases to distinguish between the two tables. This is a case where table aliases are required. However, they often make a query easier to write and to read.
JOIN to Persons Twice, using aliases, and I would suggest replacing the WHERE joins with an ANSI JOIN:
select
m.place AS place,
p1.first_name` AS first_name_sp1,
p2.first_name AS first_name_sp2
from
marriage m
INNER JOIN persons p1
ON m.spouse1 = p1.id
INNER JOIN persons p2
ON m.spouse2 = p2.id

Is the use of cursor needed to achieve the following query?

Consider the database:
A Company has zero or more Branch companies
A Company has zero or more Emails
A Branch has zero or more Emails
And consider the following instance of that database:
1 Company with 2 Branches
The Company has 1 Email
Each branch has 2 Emails
(5 Emails in total)
If you prefer, check the graphical representation of that instance.
Query
I'd like to make a query (MySQL) that retrieves all e-mails related to a given company (5, in the example). I couldn't find a solution, so after a bit of googling I found out that there's a thing called cursor.
Question
Is the use of cursor needed to achieve the query above? Would it be a good solution? What would be your solution to the query above?
(tables are defined below)
My idea was to retrieve all branches for a given company (that query I could make), but from there I don't know how to iterate through the branches (result of the query) and get all the e-mails.
Tables definitions in MySQL
-- Database tables
CREATE TABLE `company` (
`c_id` INT(11) NOT NULL AUTO_INCREMENT,
`c_name` VARCHAR(45) NOT NULL,
PRIMARY KEY (`c_name`),
UNIQUE KEY `c_id` (`c_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
CREATE TABLE `branch` (
`b_id` INT(11) NOT NULL AUTO_INCREMENT,
`c_id` INT(11) NOT NULL,
`b_name` VARCHAR(45) NOT NULL,
PRIMARY KEY (`b_name`),
UNIQUE KEY `b_id` (`b_id`),
KEY `c_id` (`c_id`),
CONSTRAINT `branch_ibfk_1` FOREIGN KEY (`c_id`)
REFERENCES `company` (`c_id`)
ON DELETE CASCADE
ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
CREATE TABLE `email` (
`e_id` INT(11) NOT NULL AUTO_INCREMENT,
`e_addr` VARCHAR(45) NOT NULL,
PRIMARY KEY (`e_addr`),
UNIQUE KEY `e_id` (`e_id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8
CREATE TABLE `c_email` (
`c_id` INT(11) NOT NULL,
`e_id` INT(11) NOT NULL,
PRIMARY KEY (`c_id`,`e_id`),
KEY `e_id` (`e_id`),
CONSTRAINT `c_email_ibfk_1` FOREIGN KEY (`c_id`)
REFERENCES `company` (`c_id`)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT `c_email_ibfk_2` FOREIGN KEY (`e_id`)
REFERENCES `email` (`e_id`)
ON DELETE CASCADE
ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8
CREATE TABLE `b_email` (
`b_id` INT(11) NOT NULL,
`e_id` INT(11) NOT NULL,
PRIMARY KEY (`b_id`,`e_id`),
KEY `e_id` (`e_id`),
CONSTRAINT `b_email_ibfk_1` FOREIGN KEY (`b_id`)
REFERENCES `branch` (`b_id`)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT `b_email_ibfk_2` FOREIGN KEY (`e_id`)
REFERENCES `email` (`e_id`)
ON DELETE CASCADE
ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8
-- Example of query
-- Retrieving all e-mails of a given branch
SELECT e_addr
FROM email AS _em
JOIN b_email AS _be ON _be.e_id = _em.e_id
JOIN branch AS _br ON _br.b_id = _be.b_id
WHERE b_name = #bra2;
-- How to retrieve all e-mails related to a given company
-- (e-mails from the company itself and also from all of its branches)?
-- ?
No, you don't need a cursor for this. You can do this with SQL -- much better than a cursor. It is something like:
select *
from ((select ce.c_id, e.email
from c_email ce join
email e
on e.e_id = ce.e_id
) union all
(select b.c_id, e.email
from branch b join
b_email be
on b.b_id = be.b_id join
email e
on be.e_id = e.e_id
)
) e
where ce.c_id = X;
EDIT:
You can add b_id into the second subquery but not the first. Perhaps you could do:
select *
from ((select ce.c_id, e.email, NULL as b_id
from c_email ce join
email e
on e.e_id = ce.e_id
) union all
(select b.c_id, e.email, b.b_id
from branch b join
b_email be
on b.b_id = be.b_id join
email e
on be.e_id = e.e_id
)
) e
where ce.c_id = X
order by c_id, b_id;

Joining 3+ tables using SQL displaying too many results

im trying to create a query to join these tables together using this method below. However it is repeating results and they are not linking up correctly. as in the same rating comment would be on about 4/5 different results etc. its producing 18ish results when im expecting 3. would anyone be willing to help me with this problem?
SELECT a.Company_name,
f.Job_ID,
f.Job_Name,
b.User_Name,
c.Comments,
c.Reliability,
c.Rating
FROM company a,
Users b,
Ratings c,
UserCompJobRating d,
Company_Job e,
Jobs f
WHERE d.Comp_job_ID = e.Comp_Job_ID
AND b.users_ID = d.users_ID
AND c.Rating_ID = d.Rating_ID;
Many Thanks,
Andrew
ok i tried this and it is saying e.Users_ID is an unknown column in 'on clause'
SELECT a.Company_name,
b.Job_ID,
b.Job_Name,
c.User_Name,
d.Comments,
d.Reliability,
d.Rating
FROM Company a, UserCompJobRating e, Jobs b
INNER JOIN Users c
ON c.Users_ID = e.Users_ID
inner join Company_Job f
on e.Comp_Job_ID = f.Comp_Job_ID
inner join Ratings d
on d.Rating_ID = e.Rating_ID;
I'm assuming im close, however way off at the same time?
Ill try to give you some more information:
UserCompJobRating has a primary key UCJR_ID and 3 foreign keys of Comp_Job_ID, Users_ID and Rating_ID
Company_Job table as a primary key Comp_Job_ID, and 2 foreign keys Job_ID, Company_ID
Ratings Table has just the Rating_ID as a primary key and the rest just to do with the rating information
Users Table has a Users_ID as a primary key and basic user information address etc etc
Jobs Table has a Job_ID primary key and basic information about the job, such as name, price, etc.
Company Table has Company_ID as a primary key and the basic company information, similar to the Users table.
Here are the definations:
CREATE TABLE `company` (
`Company_ID` int(11) NOT NULL AUTO_INCREMENT,
`Company_Name` varchar(45) NOT NULL,
`CAddress` varchar(45) NOT NULL,
`CTown` varchar(45) NOT NULL,
`CPostcode` varchar(12) NOT NULL,
`CTelephone` varchar(45) NOT NULL,
PRIMARY KEY (`Company_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
CREATE TABLE `company_job` (
`Comp_Job_ID` int(11) NOT NULL AUTO_INCREMENT,
`Company_ID` int(11) NOT NULL,
`Job_ID` int(11) NOT NULL,
PRIMARY KEY (`Comp_Job_ID`),
KEY `Company_ID_idx` (`Company_ID`),
KEY `Job_ID_idx` (`Job_ID`),
CONSTRAINT `Company_ID` FOREIGN KEY (`Company_ID`) REFERENCES `company` (`Company_ID`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `Job_ID` FOREIGN KEY (`Job_ID`) REFERENCES `jobs` (`Job_ID`) ON DELETE NO ACTION ON UPDATE NO ACTION
CREATE TABLE `jobs` (
`Job_ID` int(11) NOT NULL AUTO_INCREMENT,
`Job_Name` varchar(45) NOT NULL,
`Job_Cost` varchar(45) DEFAULT NULL,
`Job_Avg_Time` varchar(45) DEFAULT NULL,
`Job_Avg_Cost` varchar(45) DEFAULT NULL,
`Job_Description` varchar(45) NOT NULL,
`Company_ID` int(11) NOT NULL,
PRIMARY KEY (`Job_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
CREATE TABLE `ratings` (
`Rating_ID` int(11) NOT NULL AUTO_INCREMENT,
`Comments` varchar(200) DEFAULT NULL,
`Cost` varchar(45) DEFAULT NULL,
`Reliability` varchar(45) DEFAULT NULL,
`Rating` int(11) DEFAULT NULL,
PRIMARY KEY (`Rating_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
CREATE TABLE `usercompjobrating` (
`UCJR_ID` int(11) NOT NULL AUTO_INCREMENT,
`Comp_Job_ID` int(11) DEFAULT NULL,
`Rating_ID` int(11) DEFAULT NULL,
`Users_ID` int(11) DEFAULT NULL,
PRIMARY KEY (`UCJR_ID`),
KEY `Comp_Job_ID_idx` (`Comp_Job_ID`),
KEY `Rating_ID_idx` (`Rating_ID`),
KEY `User_ID_idx` (`Users_ID`),
CONSTRAINT `Comp_Job_ID` FOREIGN KEY (`Comp_Job_ID`) REFERENCES `company_job` (`Comp_Job_ID`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `Rating_ID` FOREIGN KEY (`Rating_ID`) REFERENCES `ratings` (`Rating_ID`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `Users_ID` FOREIGN KEY (`Users_ID`) REFERENCES `users` (`Users_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
CREATE TABLE `users` (
`Users_id` int(11) NOT NULL AUTO_INCREMENT,
`User_Name` varchar(45) NOT NULL,
`UAddress` varchar(45) NOT NULL,
`UTown` varchar(45) NOT NULL,
`UPostcode` varchar(45) NOT NULL,
`UTelephone` varchar(45) NOT NULL,
`UDOB` varchar(45) NOT NULL,
PRIMARY KEY (`Users_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
The query needs to look something like this i.e. use this form
SELECT a.Company_name,
f.Job_ID,
f.Job_Name,
b.User_Name,
c.Comments,
c.Reliability,
c.Rating
FROM company a
INNER JOIN Users b
ON a.???? = b.???
Since I dont have your table definitions I cant help you with the JOIN conditions. Show us the tables definition and we would be able to help.
UPDATE:
So based on your table structures you will be looking for something like this:
SELECT *
FROM company cmp
INNER JOIN company_job cmpjb
ON cmp.Company_ID = cmpjb.Company_ID
INNER JOIN jobs jb
ON cmpjb.Job_ID = jb.Job_ID
INNER JOIN usercompjobrating ucmpjbr
ON ucmpjbr.Comp_Job_ID = ucmpjbr.Comp_Job_ID
INNER JOIN users usr
ON usr.Users_id = ucmpjbr.Users_ID
INNER JOIN ratings rat
ON rat.Rating_ID = ucmpjbr.Rating_ID
Note you cannot use the folder table in this join as there are no primary/foreign key relationships to any of the other tables from the folder table.
I would suggest that you carefully dissect this query and let me know if you need to understand the details.
One thing to clarify, what is company_id in table jobs?
select ... (necessary fields to select)
from company c
join company_job cj using (company_id)
join jobs j using (job_id)
join usercompjobrating ucjr using (comp_job_id)
join ratings using (rating_Id)
join users using (users_id)

Can I do it with one query?

SELECT `invites`.`id`, `invites`.`from`, `invites`.`to`, `invites`.`group_id`
FROM `invites`
WHERE `invites`.`to` = '33'
It gets ID of user that sent invite and ID of user that is invited. And, of course, ID of group they invited each other. I need to display usernames of them, but they are stored in another table. The same goes for groups. Info about them is stored in another table.
I could make new queries to get that info from IDs, but is it worth it? Can I do it with only one query?
Edit:
Structure:
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`surname` varchar(50) NOT NULL,
PRIMARY KEY (`id`),
);
CREATE TABLE `invites` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`group_id` int(10) unsigned NOT NULL,
`from` int(10) unsigned NOT NULL,
`to` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `groups` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
);
A join is always worst it:
SELECT `invites`.`id`,
`invites`.`from`,
`invites`.`to`,
`invites`.`group_id`,
`toUsers`.`name` as toUserName,
`fromUsers`.`name` as fromUserName,
`groups`.`name` as groupName
FROM `invites`
INNER JOIN `users` AS toUsers
ON `invites`.`to` = toUsers.id
INNER JOIN `users` AS fromUsers
ON `invites`.`from` = fromUsers.id
INNER JOIN `groups`
ON `invites`.`group_id` = `groups`.`id`
WHERE `invites`.`to` = '33'
The only thing you have to keep in mind is to have foreign keys on from, to and group_id, and have primary keys on Id in tables Users and Groups. Then your query will be as fast as you need.
So I advise to run this :
ALTER TABLE `invites`
ADD CONSTRAINT FK_invites_to FOREIGN KEY (`to`) REFERENCES users(id),
ADD CONSTRAINT FK_invites_from FOREIGN KEY (`from`) REFERENCES users(id),
ADD CONSTRAINT FK_invites_group FOREIGN KEY (`group_id`) REFERENCES groups(id)
See some doc : http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html
You can use a JOIN:
SELECT invites.id, invites.from, invites.to, invites.group_id, group.name, u1.name, u2.name
FROM invites, user as u1, user as u2, group
WHERE invites.from = u1.id
AND invites.to = u2.id
AND group.id = invites.group_id
AND invites.to = '33'
Assuming your tables are called user and group and your fields name. You may have to put the backticks back on the field names because FROM is a reserved keyword.
I'd use a join too, but I'd create a view first that joins invites to users, then join two of those together - it means not having to repeat the join between invite and user.