Basic MySQL project: defining keys and on delete cascades - mysql

I am a beginning student in MYSQL and I have the following assignment:
Create a database with the name UNIVERSITY. Then create tables in UNIVERSITY according to the following schemas:
Student(Sid; Sname;GPA)
MajorsIn(Sid;Major)
Book(BookNo; Title; Price)
Cites(BookNo;CitedBookNo)
Buys(Sid;BookNo)
A student can have multiple Majors or no major. A tuple (b,c) in the relation
Cites indicates that the book with book number b cites the book with book number c.
Where appropriate, add “ON DELETE CASCADE” statements with the foreign key
constraints.
Here is the code I have so far:
CREATE DATABASE University;
CREATE TABLE Stu ( sid INTEGER,
gpa REAL,
PRIMARY KEY (sid) )
CREATE TABLE Majorsin ( sid INTEGER,
Major CHAR(10),
PRIMARY KEY (sid) )
CREATE TABLE Book ( bookno INTEGER,
title CHAR(10),
price REAL,
CREATE TABLE Cites ( bookno INTEGER,
citedbookno INTEGER,
CREATE TABLE Buys ( sid INTEGER,
bookno INTEGER,
PRIMARY KEY (sid) )
My question is: what changes to the above code do I need to make to meet the requirements? In particular, what changes do I need to make in terms of defining the keys and where do i need to put "ON DELETE CASCADES?'
Sorry if this is a basic/general question: I'm a noob and could use some help getting through this first assignment.
Thanks!

Related

SQL-linking two tables with a third table

I have two tables Students and Courses.
I have to create a mapping table to link these two tables with a set of information.
For eg: Mary Murphy from **Students ** table is to be linked with Courses table with web designing course that she is taking.
How can I do this??
Thank you in advance.
You would use a third table, studentCourses would be a reasonable name. It would look something like this:
create table studentCourses (
studentCourseId int auto_increment primary key,
studentId int,
courseId int,
constraint fk_studentcourses_student foreign key (studentId) references students (studentId),
constraint fk_studentcourses_course foreign key (courseId) references students (courseId)
);
You might include other information, such as the enrollment date.

Adding primary/foreign keys and referencing other tables

Im having some troubles with key referencing. The Error comes from when i try to insert data into Table Mark
INSERT INTO Mark(examID, studentID, result, occured, noOFAttempts)
VALUES ('B10', '1', '67', '11-JUL-07', '1');
I get the error:
integrity constraint violated - parent key
not found
Context :
The tables Exam and Student represent data about college exams and
students. The exam results for the students, including the number of
attempts a student has had at an exam (noOfAttempts), are recorded in
table Mark by using the id column from Exam and the id column from
Student. Both id columns have unique values . A student has only the
latest result recorded for each exam.
Write a SQL command to create the Mark table. Include the primary keys
and foreign keys apparent in the tables specified above.
CREATE TABLE Exam (
id VARCHAR(255),
subject VARCHAR(255),
noOfStudents INT,
PRIMARY KEY (id));
-
CREATE TABLE Student (
id INT,
name VARCHAR(255),
PRIMARY KEY (id));
-
CREATE TABLE Mark (
examID VARCHAR(255),
studentID INT,
result INT,
occured DATE,
noOFAttempts VARCHAR(255),
FOREIGN KEY (noOFAttempts) REFERENCES Exam(id),
FOREIGN KEY (noOFAttempts) REFERENCES Student(id));
How do i fix the error i know its to do with wrong referencing, thanks
Some of the logic behind the Mark table makes sense to me. It relates exams to the students who took those exams. But the motivation to make noOfAttempts a foreign key does not seem to serve much purpose. There are two foreign keys in that table, examID and studentID, and the combination of these two fields is also a primary key. Here is what the Mark definition might look like to avoid these errors:
CREATE TABLE Mark (
examID VARCHAR(255),
studentID INT,
result INT,
occured DATE,
noOFAttempts VARCHAR(255),
FOREIGN KEY (examID) REFERENCES Exam(id),
FOREIGN KEY (studentID) REFERENCES Student(id),
PRIMARY KEY (examID, studentID)
)
Again, I don't see the point of making noOfAttempts a key of any kind, rather I think it should just be one regular column in the Mark table.
Edit per request from Gordon:
When you made your insert, you attempted to create a record in Mark which referred to parent records which did not exist. In the case of your original table, you attempted to insert '1' as the noOfAttempts, but this ID did not exist in either the Exam and/or Student tables.

MySQL Creating Tables from ER Diagram

I am working on creating a database from an ER diagram however I don't think some of my primary and foreign keys are correct. The tables that I don't think they are correct in is the primary key in section and the FK and PK in enrolled table. I also don't think I am properly enforcing my FK constraints so that I can detect referential integrity violations.
Here is the ER Diagram I am basing my database off of.
Here are the tables that I have made
CREATE TABLE Student
(
StudentId INTEGER,
FName VARCHAR(20),
LName VARCHAR(20),
DOB CHAR(10),
Major VARCHAR(20),
PRIMARY KEY(StudentId)
);
CREATE TABLE Phone
(
sID INTEGER,
Pnumber CHAR(20),
Type CHAR(3),
PRIMARY KEY(Pnumber)
);
CREATE TABLE Class
(
ClassId VARCHAR(6),
Description VARCHAR(30),
NumCredits Integer,
Prereq VARCHAR(20),
PRIMARY KEY(ClassId)
);
CREATE TABLE Section
(
ClassId VARCHAR(6),
SecNo CHAR(10),
Semester CHAR(4),
ClassRoom VARCHAR(6),
TimeOffered VARCHAR(18),
PRIMARY KEY(SecNo),
FOREIGN KEY(ClassId) REFERENCES Class(ClassId)
);
CREATE TABLE Enrolled
(
StudentId INTEGER,
SecNum VARCHAR(40),
ClassId VARCHAR(8),
Semes VARCHAR(6),
GorDD VARCHAR(30)
FOREIGN KEY(ClassId) REFERENCES Section(ClassId),
FOREIGN KEY(StudentId) REFERENCES Student(StudentId)
);
CREATE TABLE Professor
(
EmpId INTEGER,
FName VARCHAR(10),
LName VARCHAR(10),
Dept VARCHAR(2),
QualClass VARCHAR(40),
PRIMARY KEY (EmpId)
);
CREATE TABLE Teaches
(
Class VARCHAR(5),
Section INTEGER,
Semester CHAR(4),
EmpId INTEGER,
FOREIGN KEY (EmpId) REFERENCES Professor(EmpId)
);
CREATE TABLE Qualified
(
EmpId INTEGER,
ClassId VARCHAR(5)
);
Thank you for the help in understanding how to create a DB from an ER diagram.
You really should have a simple, standardized, AUTO_INCREMENT PRIMARY KEY for every table. That makes referring to specific records a lot easier. It's also better to refer to tables by their primary key only when building relationships. String primary keys can be trouble, especially if those strings can change.
Additionally, your arbitrary limitations on string lengths is extremely annoying. Who are you to say people should only have names twenty characters long, or professors can have names only ten long? That's really sloppy. Unless you've got a very good reason, leave it wide open for these sorts of free-form fields, default VARCHAR(255). Hard drives are measured in terabytes today and you'd need to have a hundred million students to fill up your drive with name data.
Otherwise, as a database this is okay. I'd probably discard this schema entirely and rebuild from your entity diagram, a great tool to have by the way, using the conventions of whatever development framework I was using. For example, Ruby on Rails, Django, Drupal, and Tapestry will all have their own ideas on how to name tables.
After a quick look, it looks to me like you would want to have a compound primary key for Section made up of ClassId, SecNo, and Semester assuming those three attributes make up the uniqueness scope for the entity of Section. You could also just have a SectionID that is unique (such as an auto-incrementing int)
For Enrolled, I would make an auto-incremented primary key and have a foreign key that links to the Section table depending on how you solve that entity/table's uniqueness.
Hope this helps. Of course, there are many ways to go about this.
It is usually more useful and more practical to use primary keys specific to the database domain because in real life most entities don't have truly unchanging and unique keys perfectly suited for primary keys.
For example, data entry errors may necessitate the change of a student ID in the database. If you use a property that ends up changing then you'll have to create (effectively) a new student for every change in primary key(StudentId).
The alternative solutions:
Use an automatic key in the database and make the StudentId unique but not primary.
Use a StudentId as the primary key and have it be auto updated every
time it changes in the parent table.
I don't recommend the second option because it is just a workaround the old problem.

Creating a table with a couple as primary key in MySQL Server [duplicate]

This question already has an answer here:
Syntax error due to using a reserved word as a table or column name in MySQL
(1 answer)
Closed 8 years ago.
I have 2 tables:
Authors(id, name, add, DOB) where the fields are INTEGER, CHAR(20), CHAR(20), DATE respectively. Primary key = id.
Books(bid, title, publisher) where the fields are INTEGER, CHAR(20), CHAR(20) respectively. Primary key = bid.
I want to create another table Write with fields aid, bid, datePublished, where:
aid = INTEGER ... this is actually the id from Authors.
bid = INTEGER ... this is actually the bid from Books
Primary Key = (aid, bid).
How do I do this?
I tried the following lines of code, and all of them gave syntax errors:
CREATE TABLE Write (
aid INTEGER,
bid INTEGER, datePublished DATE,
PRIMARY KEY NONCLUSTERED (aid,bid),
FOREIGN KEY (aid) REFERENCES Authors(id),
FOREIGN KEY (bid) REFERENCES Books(bid)
);
CREATE TABLE Write (
aid INTEGER,
bid INTEGER,
datePublished DATE,
PRIMARY KEY (aid,bid)
);
Funny problem you're having. The reason is that Write is a reserved keyword in mysql and you can only use it as an identifier if you suround it by backticks in your queries. I recomend you picking another name or, if you really want to use Write, replace your create query with
CREATE TABLE `Write` (
aid INTEGER,
bid INTEGER,
datePublished DATE,
PRIMARY KEY (aid,bid)
);
Just remember that any other query on the table Write would require the backticks as well, which might lead to annoying errors if someone forgets them.
Write is a reserved word, no table can be named that (it can using back tics but to make your life easy stay away from names that requires back tics).
Here is the complete schema
http://sqlfiddle.com/#!2/dfe22/1
Try this :
CREATE TABLE Write (aid INTEGER, bid INTEGER, datePublished DATE PRIMARY KEY (aid,bid));

How to create a table that uses a whole other foreign table?

Let's say I have this:
CREATE TABLE `classes`
(
`class_ID` INT AUTO_INCREMENT,
FOREIGN KEY (`student_ID`) references `students`(`student_ID`),
PRIMARY KEY (`class_ID`)
)
ENGINE = InnoDB;
The thing here is that each class refers to a single student. But I want it to refer to a whole other table of students, for example:
CREATE TABLE `students`
(
`student_ID` INT AUTO_INCREMENT,
`name` VARCHAR(20) NOT NULL,
PRIMARY KEY (`student_ID`)
)
ENGINE = InnoDB;
Hence, I want multiple student tables, which each table associated to a class. How can I do this? Do i have to declare a single table (e.g. students1, students2, etc.) for each class?
Thanks!
The answer to this will be a little difficult to understand at first. After a while it becomes natural. Is is a well-known design pattern. You need a third table:
create table students_in_courses(studentid, courseid)
In this table you have a row for each student and each course that student is in. You can turn this sentence around: A row for each course and each student that is in this course.
It is a "link table". It is used for M:N mappings.
You can think of this table as an entity, just like students and courses. You could even add additional columns:
create table students_in_courses(studentid, courseid, date_entered, date_exited, grade)
A constant number of tables is enough.
Let me try a different explanation: We could store the information which student is in which course by saving a matrix with the students as its rows and the courses as its columns. Every cell has a bool: student is in this course yes/no.
Now we save this entire matrix in a table like this:
create table students_in_courses(studentid, courseid, is_in_course bit) primary key(studentid, courseid)
For each cell a row. Now we delete all rows with is_in_course = 0 and drop that column because it only contains 1's now. We are back at the original solution. Our "link-table" stores the non-zero cells of the cross-product matrix of the two tables.
No. you create a single table that has foreign keys referencing both tables:
CREATE TABLE students_classes (
student_id int,
classes_id int,
PRIMARY KEY (student_id, classes_id),
FOREIGN KEY (student_id) REFERENCES students (student_ID),
FOREIGN KEY (classes_id) REFERENCES classes (class_ID)
);
That way you can have student (example) #7 in classes (#53 and 37 and 83), student #12 in classes (#53, #212, #7), etc... without conflict.