I want to create a join table between two or more tables.
The tables are Student, and course.
Join table will be enrolled.
the business rule is that a student can only enroll in one course at a time.
I want to prevent a user from creating additional enrollments after making 1 enrollment in a course.
I am not sure what type of contraint this will be, or if its even possible.
Can anyone help?
thank you
note: I dont think it is possible to create a Primary key as the primary key of another table, ie the studentID of the student table. If i could I would. breaks the rules i think. This would be a foreign key which is not unique.
If the business rule should be ignored, and assume that a student naturally will only enroll in one course at a time.. maybe ill stop worrying...
You could create a unique index for the id_student but this provably will bring problems if a student try to register in other course later. You shoud include the id_course into the unique constraint.
ALTER TABLE table_name ADD CONSTRAINT constraint_name UNIQUE(studentId, course_id)
Other solution could be creating a Trigger.
The trigger should be a "before insert" trigger. This one should serch for information related to the student in the table, if the table doesn´t has information then insert information, else do nothing.
CREATE TRIGGER 'ONE_STUDENT_PER_COURSE'
BEFORE INSERT ON 'Enrollments'
FOR EACH ROW
BEGIN
DECLARE student_id INT;
SELECT n.id_student INTO student_id
FROM table_enrollments n
`IF student_id IS NULL THEN
/* I DON´T REALLY KNOW EXACTLY THE SINTAXIS FOR INSERTING DATA OF THE BEFORE INSERT FOR YOU VERSION OF MYSQL
BUT TRY THIS ONE
*/
INSERT INTO table_enrollments (student_id, course_id) SELECT student_id, course_id FROM inserted
END IF;
END; $$`
You can create unique index in join table.
CREATE UNIQUE INDEX index_name
ON your_join_table (studentId);
Each table can have a primary key. Two tables can have the same primary key defined. (But the implementation depends on the Entity Relationship Model, what we've discovered about the entities and relationships between the entities.
Based on the information provided in the question, a possible implementation of an enrollment table:
CREATE TABLE current_enrollment
( student_id INT UNSIGNED NOT NULL COMMENT 'pk, fk ref student.id'
, course_id INT UNSIGNED NOT NULL COMMENT 'pk, fk ref course.id'
, PRIMARY KEY (student_id, course_id)
, CONSTRAINT FK_currrent_enrollment_student FOREIGN KEY ( student_id )
REFERENCES student (id) ON UPDATE CASCADE ON DELETE RESTRICT
, CONSTRAINT FK_currrent_enrollment_course FOREIGN KEY ( course_id )
REFERENCES course (id) ON UPDATE CASCADE ON DELETE RESTRICT
)
The datatypes of the foreign key columns must match the datatypes of the referenced columns; in this example, i've assumed primary key columns id in both student and course, defined as datatype INT UNSIGNED
In this example, the PRIMARY KEY constraint enforces a unique constraint on the combination of (student_id,course_id). An attempt to insert a second enrollment (same student in the same course) would be a duplicate row, and that would throw a constraint violation, preventing the row from being added.
If enrollment turns out to be an entity in the model, with its own attributes, I'd opt to add a separate id column as a surrogate primary key, with a unique constraint on (student_id,course_id)
CREATE TABLE current_enrollment
( id INT UNSIGNED NOT NULL COMMENT 'pk'
, student_id INT UNSIGNED NOT NULL COMMENT 'fk ref student.id'
, course_id INT UNSIGNED NOT NULL COMMENT 'fk ref course.id'
, enrollment_dt DATETIME
, status VARCHAR(8)
, approval_by VARCHAR(8)
, PRIMARY KEY (id)
, CONSTRAINT current_enrollment_UX1 UNIQUE KEY (student_id, course_id)
, CONSTRAINT FK_currrent_enrollment_student FOREIGN KEY ( student_id )
REFERENCES student (id) ON UPDATE CASCADE ON DELETE RESTRICT
, CONSTRAINT FK_currrent_enrollment_course FOREIGN KEY ( course_id )
REFERENCES course (id) ON UPDATE CASCADE ON DELETE RESTRICT
)
Related
I am trying to create two tables
CREATE TABLE Submissions
(
quiz_ID INT(2) UNSIGNED,
quiz_duration TIME,
student_ID INT(2) UNSIGNED,
attempt_date date,
PRIMARY KEY (quiz_ID, student_ID)
);
and
CREATE TABLE Students
(
student_ID INT(2) UNSIGNED,
student_name VARCHAR(100),
PRIMARY KEY (student_ID),
FOREIGN KEY (student_ID) REFERENCES Submissions(student_ID)
);
However, when I try to create the second table, it gives me an error
ERROR 1822 (HY000): Failed to add the foreign key constraint. Missing index for constraint 'students_ibfk_1' in the referenced table 'Submissions'
How do I fix it?
A foreign key must reference a primary key. You have defined the primary key of SUBMISSIONS as a compound key of (quiz_ID, student_ID). Consequently this does not match the foreign key reference of STUDENTS, where you attempt to reference a single column Submissions(student_ID). That's why you get the error.
But let's drill down into this. You tagged your question [database-design], and that was a good call because this issue arises from your data model.
A student can (presumably) participate in more than one quiz and therefore have more than one submission. This indicates that your data model is wrong. Whenever we have a 1:M relationship the 1 end (in this case STUDENTS) is referenced by a foreign key on the M end (i.e. SUBMISSIONS).
It also seems likely that your data model is missing a table for QUIZZES, and SUBMISSIONS should in fact be an intersection table.
Given all this, your tables should look like this:
CREATE TABLE Quizzes
(
quiz_ID INT(2) UNSIGNED,
quiz_duration TIME
PRIMARY KEY (quiz_ID)
);
CREATE TABLE Students
(
student_ID INT(2) UNSIGNED,
student_name VARCHAR(100),
PRIMARY KEY (student_ID)
);
CREATE TABLE Submissions
(
quiz_ID INT(2) UNSIGNED,
student_ID INT(2) UNSIGNED,
attempt_date date,
PRIMARY KEY (quiz_ID, student_ID),
FOREIGN KEY (quiz_ID) REFERENCES Quizzes(quiz_ID),
FOREIGN KEY (student_ID) REFERENCES Students(student_ID)
);
You have the foreign keys in the wrong order. The submissions should have the foreign key constraint. So:
CREATE TABLE Submissions (
quiz_ID INT(2) UNSIGNED,
quiz_duration TIME,
student_ID INT(2) UNSIGNED,
attempt_date date,
PRIMARY KEY (quiz_ID, student_ID),
CONSTRAINT fk_subsmissions_student_id FOREIGN KEY (student_id) REFERENCES students(student_id)
);
Of course, the Students table needs to be created, before the foreign key is defined.
Excuse the possibly poorly posed question, let me explain.
I have a table: Doctor, and a table: Patient
Doctor and Patient have the same primary key, 'person_id'
A patient can also be a doctor and vice versa, in which case they'd have the same person_id
Is this allowed?
What kind of relationship would I use between these tables?
Would I allow auto-increment for the primary keys on both?
How would I model this in MySQL Workbench?
Sounds to me like Doctor and Patient are sub-classes of Person. If having a relationship between the instances of Doctor and Patient is important, I would make person_id in those tables a foreign_key reference to a new person superclass table:
e.g.
CREATE TABLE `person`
( id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT 'PK person.id'
, ...
) ...
CREATE TABLE `doctor`
( person_id BIGINT PRIMARY KEY COMMENT 'PK, FK ref person.id'
, ...
, CONSTRAINT FK_doctor_person FOREIGN KEY person_id REFERENCE person (id)
ON UPDATE CASCADE ...
, ...
) ...
CREATE TABLE `patient`
( person_id BIGINT PRIMARY KEY COMMENT 'PK, FK ref person.id'
, ...
, CONSTRAINT FK_patient_person FOREIGN KEY person_id REFERENCE person (id)
ON UPDATE CASCADE ...
, ...
) ...
This is just one possible approach. Without more context about the problem space, what problems we are trying to solve, we can't make a definitive recommendation.
Which is better method among below:-
Using unique column name for each column, primary and foreign keys among all table.
Example 1:
CREATE TABLE projects (
project_id PRIMARY KEY,
project_name VARCHAR(30)
client_id INT,
fk_project_user_id INT, ( FOREIGN KEY )
projects_created_by INT, ( FOREIGN KEY )
);
CREATE TABLE clients (
client_id PRIMARY KEY,
client_name varchar(20),
fk_client_user_id INT,( FOREIGN KEY )
client_created_by INT, ( FOREIGN KEY )
)
Don't care about the uniqueness of each column name for each primary and foreign keys among all tables.
Example 2:
CREATE TABLE projects (
id PRIMARY KEY,
project_name VARCHAR(30)
client_id INT, ( FOREIGN KEY )
fk_user_id INT, ( FOREIGN KEY )
created_by INT ( FOREIGN KEY )
);
CREATE TABLE clients (
id PRIMARY KEY, (Same as above table)
client_id INT,
client_name varchar(20),
fk_user_id INT, ( FOREIGN KEY ) (Same as above table)
fk_client_id int, ( FOREIGN KEY )
created_by INT ( FOREIGN KEY ) (Same as above table)
);
When we plan database for big ERP having multiple tables and relationships among all? I have used a different name for each key to avoiding ambiguous error when we join two tables.
What is the best solution?
Naming conventions are up to you. Which naming convention you decide to use is not important. What's important is that you follow your own convention consistently, and document it so that other developers know how to understand your code and your schema.
Some people choose to give every table a primary key named id. If every one of their tables must have a column named id, then they can write reusable code for certain queries against any table.
However, this convention does not account for compound primary keys. Also if your query does a join, the query result set may have multiple columns named id unless you define column aliases.
When I design a database, I name my primary key in a descriptive way. projects.project_id for example. This avoids the problem of duplicate column names in a result set of a join. It also makes it more clear what the column means when you see it in a query or a result set.
I like to name the foreign key the same as the primary key column it references, when I can do it without resulting in a conflict.
But consider this example, where there are multiple foreign keys in the same table that reference Users.user_id.
CREATE TABLE Bugs (
bug_id INT PRIMARY KEY,
description TEXT NOT NULL,
reported_date DATETIME NOT NULL,
user_reported_by INT NOT NULL,
user_assigned_to INT,
user_verified_by INT,
FOREIGN KEY (user_reported_by) REFERENCES Users(user_id),
FOREIGN KEY (user_assigned_to) REFERENCES Users(user_id),
FOREIGN KEY (user_verified_by) REFERENCES Users(user_id)
);
You can't assume you can use a common column name, because it's normal to need multiple foreign keys referencing the same table, as in the example above. Therefore you must allow the FK column name to be different from the PK it references.
project assignment is n to n relationship where n can be zero.
pid is primary key for the project table
eid is primary key for the employee table
a project may not be assigned to any employee.similary an employee may not have any project in his hand.
how to write this query? eid should take value as null or the value from the emp table.
pid should either take null or the value from the table project.
IS IT CORRECT.
CREATE TABLE Proj_Assign
(
eid VARCHAR(25),
pid VARCHAR(25),
PRIMARY KEY(eid,pid),
FOREIGN KEY eid REFERENCES employee(eid),
FOREIGN KEY pid REFERENCES project(pid)
);
Give this way:
FOREIGN KEY (t_eid) REFERENCES parent(eid)
ON DELETE CASCADE
Instead of using same eid twice. It is explained in the documentation.
Also, the original parent table should be there before you create this table and you need to manually insert the queries this way:
INSERT INTO `Proj_Assign` (`eid`, `pid`) VALUES (1, 1);
Whatever query you have written is right as per documentation.
I have 2 tables, customers and affiliates. I need to make sure that customers.email and affiliates.email are exclusive. In other words, a person cannot be both a customer and an affiliate. It's basically the opposite of a foreign key. Is there a way to do this?
You can use a table that stores emails and have unique constrain on the email, and reference that table from the customer and affiliate. (still need to ensure that there are no 2 records referencing the same key)
You can use trigger before insert and before update to check if the email is not present.
Or you can leave this validation to the application logic - not in the database, but in the applicationc ode.
There is no key you can do this with, but it sounds like you shouldn't be using two tables. Instead, you can have one table with either customer/affiliate data (that needs to be unique in this table) and another table that has the type (customer/affiliate).
CREATE TABLE People (
pplid,
pplEmail,
ptid,
UNIQUE KEY (pplEmail)
)
CREATE TABLE PeopleType (
ptid,
ptType
)
INSERT INTO PeopleType VALUES (1, 'affiliates'), (2, 'customers');
You can try the following.
Create a new table, which will be a master for customers and affiliates:
CREATE TABLE party
(
id int not null auto_increment primary key ,
party_type enum('customer','affiliate') not null,
email varchar(100),
UNIQUE (id,party_type)
);
--Then
CREATE TABLE customer
(
....
party_id INT NOT NULL,
party_type enum('customer') NOT NULL DEFAULT 'customer',
PRIMARY KEY (party_id,party_type)
FOREIGN KEY (party_id,party_type) REFERENCES party(id,party_type)
);
CREATE TABLE affiliates
(
....
party_id INT NOT NULL,
party_type enum('affiliate') NOT NULL DEFAULT 'affiliate',
PRIMARY KEY (party_id,party_type)
FOREIGN KEY (party_id,party_type) REFERENCES party(id,party_type)
)
-- enum is used because mysql still doesn't have CHECK constraints
This way each party can be only of one type