I have a table named group Info. It has three fields namely id,user_id, and group_id.
My question is how to assign unique users to a group i-e same user may not be repeated in a same group.
Table structure for group Info is as follows;
id int(11) Auto increment,Primary key NOT NULL,
user_id int(11) Not Null,
group_id int(11) Not Null
I have made the user_id unique.But there are two groups(2 group_id(1 and 2)).Selecting users for groupB gives error duplicate entry.
user_id = 1,2,3,4,5,6,7,8;
group_id= 1,2;
Kindly help me how to solve this.Iam not good in english so apologies for my language.
ALTER TABLE `tbl_name` ADD UNIQUE (
`col1` ,
`col2`
);
Change col1 with user_id and col2 with group_id and tbl_name with your table name.
If user_id is unique, then you probably shouldn't be creating a join table: just add a group pointer to the user table.
If, on the other hand, a user can belong to more than one group, then your current design is probably appropriate, but you shouldn't make user_id unique (although you might want to make a unique composite key on the combination of user_id and group_id).
Related
I am trying to insert some data into the table User. The User table has 2 foreign keys: StudentID and StaffID.
I want to be able to enter either StaffID or StudentID which should link to the relevant table(that already has either the StudentID or StaffID). The table User can only have StaffID or StudentID. Can Anyone help?
INSERT INTO `User` (`UserName`, `Email`, `StudentID`,`StaffID`,`Paasword`)
VALUES ('phill', 'ph#lms.com', '', '2201','654321');
Ok, so prepare yourself. This answer is long, but thorough.
Short Answer:
As referenced in this answer by #HLGEM you can accomplish what you're asking by making the primary keys in the STAFF and STUDENT table, presumably the values StaffID and StudentID NULLABLE. Here is the relevant snippet from his answer:
To allow nulls in an FK generally all you have to do is allow nulls on the field that has the FK. The null value is separate from the idea of it being an FK.
You can do this in your table definition adding NULL to your create statement similar to the following by specifying:
CREATE TABLE STUDENT (
StudentID INT UNSIGNED NULL PRIMARY KEY AUTO_INCREMENT
...
)
The above is an example of how to apply this to the STUDENT table. The STAFF table would have a similar approach. Note, the extra values are there as a suggestion based on general configuration that is common when configuring ID fields.
LONG ANSWER:
As #HLGEM mentioned in his answer, there are some times when it is appropriate to have a foreign key constraint that can be NULL. However, in your case, it suggestions that the data is not fully normalized. The need for a NULL foreign key can be eliminated in your case with a little table refactoring. Let's explore an additional possibility when designing your database tables:
Case Study:
Let's begin with the following assumption. Since you said in your question:
I want to be able to enter either StaffID or StudentID which should link to the relevant table(that already has either the StudentID or StaffID). The table User can only have StaffID or StudentID
It is probably a safe assumption to say that a user has to be a staff member or a student but not both. That assumption makes a strong use case for having a UserType table. Let's alter the USER definition to support a UserTypeId and create the USER_TYPE table:
# USER TYPE Table Definition
CREATE TABLE USER_TYPES (
UserTypeId TINYINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
UserType VARCHAR(25) NOT NULL
) ENGINE=INNODB CHARSET=UTF8;
# USER TABLE Definition
CREATE TABLE USERS (
UserId INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
Name VARCHAR(25) NOT NULL,
Email VARCHAR(50) NOT NULL,
Password VARCHAR(100) NOT NULL,
UserTypeId TINYINT UNSIGNED NOT NULL,
FOREIGN KEY(UserTypeId) REFERENCES USER_TYPES(UserTypeId)
) ENGINE=INNODB CHARSET=UTF8;
Notice that in this new schema, we no longer have a reference to StudentID or StaffID, but instead we have a UserTypeId. There are two benefits to this approach:
USERS.UserTypeId is a foreign key reference to USER_TYPES.UserTypeId but no longer has to be NULLABLE.
You can have more user types than just Student or Staff.
For our case study here, let's create two user types Student and Employee (I'll explain why I'm not using Staff here in a little). Let's also go ahead and populate the USERS table with the initial values for Phill, your employee you mentioned in your question.
INSERT INTO USER_TYPES(UserType)
VALUES("Employee"),("Student");
INSERT INTO USERS(Name,Email,Password,UserTypeId)
VALUES("phill","ph#lms.com","654321",1);
Excellent! Our new design is coming together quickly. Now let's create two additional tables, one called STUDENTS and one called EMPLOYEES. In this case, I chose to go with EMPLOYEES instead of STAFF because it allows you to be more flexible in how you define an employee. As you'll see in the definition, you can further define a user type of Employee with an ENUM value of either Faculty, Staff or Administrative. Think of this as a subtype of the general type Employee. Note that you could also create another join table like we did for USER_TYPES, for instance one called EMPLOYEE_TYPES. Either method is appropriate. I chose to use an ENUM instead of another foreign key to demonstrate an additional concept you could use if you only have a handful of choices.
So on to those last two table definitions:
# STUDENTS Table Definition
CREATE TABLE STUDENTS(
StudentId INT UNSIGNED PRIMARY KEY,
Year ENUM('Freshman','Sophmore','Junior','Senior') NOT NULL,
FOREIGN KEY(StudentId) REFERENCES USERS(UserId)
) ENGINE=INNODB CHARSET=UTF8;
# EMPLOYEES Table Definition
CREATE TABLE EMPLOYEES (
EmployeeId INT UNSIGNED PRIMARY KEY,
EmployeeType ENUM('Faculty','Staff','Administrative') NOT NULL,
FOREIGN KEY(EmployeeId) REFERENCES USERS(UserId)
) ENGINE=INNODB CHARSET=UTF8;
Notice that these two tables do not have their own Id column, but instead, reference the Id from the USERS table as a foreign key constraint. This makes sense because you have to be a user before you can be a student or an employee.
Finally, let's add some employee data for Phill:
INSERT INTO EMPLOYEES(EmployeeId,EmployeeType)
VALUES(1,"Faculty");
That was a lot, but now you'll begin to reap the benefits. Everything above was foundational in that it offers a fully normalized approach to your database layout with additional flexibility and without the need for a NULLABLE foreign key.
Retrieving data in this instance is easy and we don't even have to know if Phill is an employee or a student. Let's look at an example query:
SELECT
u.UserId,
u.Name,
u.Email,
ut.UserType,
s.*,
e.*
FROM USERS AS u
INNER JOIN USER_TYPES AS ut ON u.UserTypeId = ut.UserTypeId
LEFT JOIN STUDENTS AS s ON u.UserId = s.StudentId
LEFT JOIN EMPLOYEES AS e ON u.UserId = e.EmployeeId
WHERE u.Email = "ph#lms.com";
which returns:
+--------+--------+-------------+-----------+-----------+--------+------------+--------------+
| UserId | Name | Email | UserType | StudentId | Year | EmployeeId | EmployeeType |
+--------+--------+-------------+-----------+-----------+--------+------------+--------------+
| 1 | phill | ph#lms.com | Employee | (null) | (null) | 1 | Faculty |
+--------+--------+-------------+-----------+-----------+--------+------------+--------------+
Conclusion:
Live Example: sqlfiddle
So there you have it. By performing a LEFT JOIN between STUDENTS, EMPLOYEES and the USERS table, you'll pull back all values that exist in either of the two tables and all the default user values. From here, it's a simple as checking for NULL on StudentId or EmployeeId to determine which user type you're working with.
by constructing a brigde table I would link many salesman and group together
I've made three table like below
salesman
========
uId
salesGroupLinked
================
uId
groupId
group
======
groupId
so it should be able to allow 1 salesman can have many groups and also many groups can own by 1 salesman. But now I thought of expand the relationship.
Says I want each salesman can have their performances score for each group. Where should I put the column? If it's at group table then it's obsoleted, because groupId is unique, so it may give a score to many salesman.
Just by thinking about the problem: What is the key of the performance score? It is settings of one salesman's group. So, the settings should be on the table where they are linked. It will be unique for each pair of (salesman, group).
So the table would look like
salesGroupLinked
================
uId
groupId
PerformanceScore
put the score in the link table.
The pk on that table should still be uId and groupId, but it should also have a column for the score.
EDITED to shopw DDL statements to Create table with Primary Key
create table salesGroupLinked
( uId integer not null,
groupId integer not null,
performanceScore integer null,
Constraint PK_salesGroupLinked Primary Key clustered (uId, groupId)
)
The composite PK for this table itself guarantees that there can never be more than one row in this table with the same values for uId and groupId.
I have a given table in MySQL called inventory.. all the descriptions in table null = 'Yes' and default = 'Null'. the field names in the table are inventory, items, sales and Staff.
in inventory table I have part_no, decript,on_hand,location,unitcost, discontinue..
is it correct in stating that part_no would be my primary key as this this record can not have a duplicate value.
thank you for confirming or correcting my assumption.. Is there a query that would validate this.
did you already create your table? and could find the primary key? primary key ensure unique row and restrict duplicate value. if you want to find primary key of a table use.
SHOW KEYS FROM tablename WHERE Key_name = 'PRIMARY'
The below query gets the part_no and it's number of appearances, if you see 2 or above, then part_no can't be your primary key, and you have to select another or more primary keys. Make sure part_no IS NOT NULL !!! as you can't have null primary keys
select part_no, count(*) as appearances
from inventory
group by part_no
if you want to know it faster because of many rows, you run this
select max(appearances)
from ( select part_no, count(*) as appearances
from inventory
group by part_no )
if max is 1 you are ok. If not, add to group by and select another collumn and do the same. Then you can determine what collumn/s is/are your primary key. And with alter table, or some GUI you can change it.
I have this table:
create table user_roles
(
user_id INT UNSIGNED NOT NULL,
role_id INT UNSIGNED NOT NULL,
UNIQUE (user_id, role_id),
INDEX(id)
);
user_id and role_id are primary keys of other tables, namely user and roles. What does UNIQUE (user_id, role_id), mean? Does it mean that all user_id/role_id pairs have to be unique?
And what is INDEX(user_id) for?
UNIQUE does indeed ensure that all values that go into the fields differ from the previous.
INDEX(user_id) will create an index on the user_id field so that it is better indexed, i.e. it can be searched through faster.
Without an index, MySQL must begin with the first row and then read through the entire table to find the relevant rows.
http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html
Yes, UNIQUE(user_id, role_id) means that the combination of those two fields for any particular row cannot exist in the table more than once.
INDEX(user_id) applies an index on the user_id column, making searching on that column very fast (at some small performance expense when inserting/updating to the table)
Yes it means that user_id/role_id pairs are unique.
I'm very confused in creating Tables in MySQL because I read some PHP tutorials and the authors create two tables in their database and then linking them up later in PHP using joins.
Here's an example I got from an article..
Here the author created the table users and groups.
CREATE TABLE users (
id int(8) NOT NULL auto_increment,
name varchar(255) NOT NULL default '',
pass varchar(255) NOT NULL default '',
PRIMARY KEY (id)
) TYPE=InnoDB;
CREATE TABLE groups (
uid int(8) NOT NULL default '0',
grp varchar(255) NOT NULL default ''
) TYPE=InnoDB;
When I look at it, isn't the groups table not necessary? I mean I can just create the table this way:
CREATE TABLE users (
id int(8) NOT NULL auto_increment,
name varchar(255) NOT NULL default '',
pass varchar(255) NOT NULL default '',
grp varchar(255) NOT NULL default ''
PRIMARY KEY (id)
) TYPE=InnoDB;
In this way, I can just query the database and I don't need to join the two tables together at all.
So what's the purpose of creating two tables and not one? Please explain to me why linking together two tables is better than one.
I a lot of authentication systems 1 user can have multiple groups. Therefore 2 tables are necessary. If you want to have a good idea how to design your tables than you can have a read on database normalization.
even beter would be if you create a table for groups, a table for users, and a table for users in groups. This is because it's common to have multiple users in a group and users can have multiple groups (many to many relation). Many to many relations in relational databases are not possible. Therefor you need the extra table.
An other advantage of this system is that if you decide to change the group name than you don't need to change that name for each user. You can just change the name once and it's changed for all users.
You get something like this.
- table user
- id
- username
- password
- etc
- table groups
- id
- name
- etc
- table usergroups
- userid
- groupid
You can also have a look at FCO-IM which is a more complicated method to design databases compared to ERM, but might be handy for bigger and more complicated databases.
the keyword is 'normalization'
you have only one table. and because your lazy or tired you decide after a week to type 'mod' instead of 'moderator'... not good
if you use two (or three) tables you only have to select / type in an ID, and you can easily apply one users to multiple groups
CREATE TABLE users (
user_id int(8) NOT NULL auto_increment,
name varchar(255) NOT NULL default '',
pass varchar(255) NOT NULL default '',
PRIMARY KEY (user_id)
) TYPE=InnoDB;
CREATE TABLE groups (
group_id int(8) NOT NULL auto_increment,
name varchar(255) NOT NULL default '',
PRIMARY KEY (group_id)
) TYPE=InnoDB;
CREATE TABLE user_groups (
user_id INT(8) NOT NULL ,
group_id INT(8) NOT NULL ,
PRIMARY KEY (user_id, group_id) ,
INDEX user_id (user_id ASC) ,
INDEX group_id (group_id ASC) ,
CONSTRAINT user_id FOREIGN KEY (user_id ) REFERENCES users (user_id ) ON DELETE CASCADE,
CONSTRAINT group_id FOREIGN KEY (group_id ) REFERENCES groups (group_id ) ON DELETE CASCADE
)
ENGINE = InnoDB;
In your example (where there's only one table) you can only have a one to one relationship between a user and a group. (i.e.: A given user can only belong to one group at most.)
However, if you separate the users and groups you can easily have a much more extensive set of relationships (one to one, one to many, etc.) such as allowing a single user to belong to multiple groups, etc. whilst still being able to trivially lookup group membership for a given group. That said, you will need a third "user to group membership" table which would contain an entry for each group a given user is a member of.
That's a weird way to do it. Usually, you want a users table that has the users information (avatar, information, etc) and a groupId that is a reference to a group that exists within a groups table. Using this concept allows you to have a groups table where each group has its own information such as avatar, description, and/or groupowner. It basically reduces duplication and allows you to extend relationships.