Changing the Reference value of a Foreign Key - mysql

I have created a table 'company' having the column actor_id referencing the primary key (id) of the table 'actor'. Now I want to change the column actor_id to reference the primary key (id) of the table director. After trying to drop the foreign key, and creating a new one referencing the new table, it did not work as desired, it stayed the same - referencing the previous (actor) table. What changes should I make?
CREATE TABLE company(
id INT NOT NULL AUTO_INCREMENT,
actor_id INT NOT NULL,
CONSTRAINT aID FOREIGN KEY (actor_id) REFERENCES actor(id),
PRIMARY KEY(id)
);
ALTER TABLE company
DROP FOREIGN KEY aID,
ADD CONSTRAINT actID FOREIGN KEY (actor_id) REFERENCES director(id);

Don't see any apparent issues in the code above. I tried same in SQL Fiddle which works. You can check the link.
http://www.sqlfiddle.com/#!9/82e334c/2/0

Related

How to use a Foreign key in a table a primary key in another table

I have 3 tables. Courses,CourseDestails, CourseBooking.
Courses
CREATE TABLE Courses (
courseId int NOT NULL,
courseName varchar(255),
level varchar(255),
description varchar(255),
PRIMARY KEY (courseId)
);
CourseDetails
CREATE TABLE CourseDetails (
CourseStartDate int NOT NULL,
Location varchar(255) NOT NULL,
MaxNoPlaces int,
Length int,
Instructor varchar(255),
TotalPlacesBooked int,
NoPlacesCancelled int,
AdultPrice int,
ChildPrice int,
courseId int,
CONSTRAINT PK_CourseDetails PRIMARY KEY (CourseStartDate,Location,courseId),
FOREIGN KEY (courseId) REFERENCES Courses(courseId)
);
courseId from courses table is used as foreign key in the CourseDetails table.
Now I want to use CourseStartDate Location & courseId from CourseDetails table in another table called CourseBooking. I know how to add CourseStartDate Location as foreign keys. But I'm confused how to add courseId from courseDetails table as foreign key in the new CourseBookings Table.
I have tried the following
CREATE TABLE CourseBookings (
CourseStartDate int NOT NULL,
Location varchar(255) NOT NULL,
GuestNo int,
courseId int,
CONSTRAINT PK_CourseDetails PRIMARY KEY (CourseStartDate,Location,GuestNo,courseId),
FOREIGN KEY (courseId) REFERENCES CourseDetails.courseId(courseId),
FOREIGN KEY (CourseStartDate) REFERENCES CourseDetails(CourseStartDate),
FOREIGN KEY (Location) REFERENCES CourseDetails(Location),
FOREIGN KEY (GuestNo) REFERENCES Guest(GuestNo)
);
But there is an error saying
Can't create table 'b8040777_db1.CourseBookings'
Supports transactions, row-level locking, and foreign keys
There are several issues with the declaration of table CourseBookings.
ISSUE 1
This :
FOREIGN KEY (courseId) REFERENCES CourseDetails.courseId(courseId),
Should be written as :
FOREIGN KEY (courseId) REFERENCES CourseDetails(courseId),
ISSUE 2
One of the columns of CourseDetails, that is referenced by a foreign key of table CourseBookings, has no index.
From the documentation :
MySQL requires indexes on foreign keys and referenced keys so that foreign key checks can be fast and not require a table scan. In the referencing table, there must be an index where the foreign key columns are listed as the first columns in the same order. Such an index is created on the referencing table automatically if it does not exist.
In table CourseDetails :
courseId had an index automatically created because it references Courses(courseId)
CourseStartDate has no index but it is the first column in the index automatically generated by the primary key constraint declaration
Location has no index and it is only the second column in the primary key index --> it is not possible to create a foreign key referencing it, an error is raised when you try
SOLUTION 1
It is always possible to add the missing index to the table, by adding this to the CREATE TABLE CourseDetails statement :
INDEX idx_Location (Location)
SOLUTION 2
In your use case, I suspect that what you actually need is a multicolumn foreign key (supported in InnoDB only), that references the primary key of CourseDetails (an index already exists on these columns). This will allow you to associate each record of CourseBookings with a unique parent record in CourseDetails.
Suggestion of DDL :
CREATE TABLE CourseBookings (
CourseStartDate int NOT NULL,
Location varchar(255) NOT NULL,
GuestNo int,
courseId int,
CONSTRAINT PK_CourseDetails PRIMARY KEY (CourseStartDate,Location,courseId,GuestNo),
FOREIGN KEY (CourseStartDate,Location,courseId)
REFERENCES CourseDetails(CourseStartDate,Location,courseId),
FOREIGN KEY (GuestNo) REFERENCES Guest(GuestNo)
);
SOLUTION 3
If solution 2 fits for your use case, then it means that your schema can be optimized by creating an autoincremented integer primary key on table CourseDetails. The existing primary key can be turned into a UNIQUE constraint. Then, in table CourseBookings, you can just store a foreign key to that column.
This would give you a simple and efficient way to relate one table to the other, while avoiding duplicating information across tables (this actually leaves you with just 3 columns in CourseBookins).
In relational database design it is usually a good practice to create such a primary key on most tables. You could consider adding one to other tables too.
Example :
CREATE TABLE CourseDetails (
id int PRIMARY KEY AUTO_INCREMENT,
CourseStartDate int NOT NULL,
...
CONSTRAINT PK_CourseDetails UNIQUE (CourseStartDate,Location,courseId),
FOREIGN KEY (courseId) REFERENCES Courses(courseId)
);
CREATE TABLE CourseBookings (
id int PRIMARY KEY AUTO_INCREMENT,
courseDetailId INT NOT NULL,
GuestNo int,
CONSTRAINT PK_CourseBookings UNIQUE (courseDetailId,GuestNo),
FOREIGN KEY (courseDetailId) REFERENCES CourseDetails(id),
FOREIGN KEY (GuestNo) REFERENCES Guest(GuestNo)
);
PS, just in case :
FOREIGN KEY (GuestNo) REFERENCES Guest(GuestNo)
Does table Guest exists in your schema (you did not show the CREATE TABLE for it) ?

Make mySQL column unique for each foreign key

Let's say I have the following column in my database:
Item:
id int PRIMARY KEY,
name string,
foreign_id FOREIGN KEY
Is there a way without querying the database before insertion each time, that one foreign key cannot contain two rows with the same name?
Sure, you want to add an (unique) index for your foreign key column.
The SQL command to add that is
ALTER TABLE `mytable`
ADD UNIQUE INDEX `mytable_idx__1` (`foreign_id`);
If I understand correctly, you might want to use the UNIQUE constraint:
CREATE TABLE (
id INT PRIMARY KEY
, name VARCHAR(50) --or whatever you need
, foreign_id INT UNIQUE
FOREIGN KEY (foreign_id) REFERENCES...
);
As i Understand using FOREIGN KEY (foreign_id) REFERENCES --- will solve it. And make sure that the always make a unique key of table as foreign key for other table.
CREATE TABLE profile
(
id int NOT NULL PRIMARY KEY,
name varchar(50),
FOREIGN KEY (name)
REFERENCES member (name)
ON DELETE CASCADE
ON UPDATE CASCADE
) ENGINE=InnoDB ;

error 1215: CANNOT ADD FOREIGN KEY CONSTRAINT ; Composite Foreign key

I am getting ERROR CODE 1215: cannot add foreign key constraint for the child table.
Parent table has composite primary key. I want to use that composite primary key as foreign key in the child table.
Please guide me.
PARENT TABLE
CREATE TABLE health.procedures(
Specialty varchar(40),
Procedure_Name varchar(60),
PRIMARY KEY (Procedure_Name, Specialty)
);
CHILD TABLE
CREATE TABLE health.procedureProvided(
specialization varchar(40),
procedure_name varchar(60),
Insurance_ID int REFERENCES health.insurance (idInsurance),
Hospital_ID int REFERENCES health.hospital (idHospital) ,
Doctor_ID int REFERENCES health.doctor( idDoctor) ,
CONSTRAINT procedures_fk foreign key (specialization,procedure_name)references health.procedures(Specialty,Procedure_Name) ,
PRIMARY KEY (specialization, procedure_name, Insurance_ID, Hospital_ID, Doctor_ID)
);
You are specifying a foreign key that is invalid. Your primary key is procedure_name in health.procedure, but you are trying to create a composite foreign key in health.procedureProvided. You can't create that as a foreign key as the column Specialty in the master table is not part of the primary. A foreign key must contain all the columns in the contributing table's primary key but cannot contain values that are not in that primary key. You have three real options. 1. Specify Specialty as being a component of the primary key in procedure. Unfortunately that means the procedure will not necessarily by unique, it will be unique by specialty. 2. add a surrogate key - a system generated sequence value, uuid or something else (timestamps are not recommended). 3. Create validation tables valid_procedures and valid_specialties and use the table health.procedure as an intersection between those to provide valid procedures and correlated specialties and then you could migrate the entire primary key.

How do I make a column not null and be a foreign key in MySQL

I am trying to create a table that is a foreign key of another table and make it not null, but I am running into trouble making both happen. I was able to successfully get foreign keys working that did not require NOT NULL but I can't get both working.
Here is the line giving me trouble
CONSTRAINT instructor FOREIGN KEY (id) REFERENCES Instructor(id) NOT NULL
then I get the error:
CONSTRAINT instructor FOREIGN KEY (id) REFERENCES Instructor(id) NOT NULL,
*
ERROR at line 5:
ORA-00907: missing right parenthesis
Also, I am getting a weird error when trying to create a table (note, this table is created after creating the table that contains the above error) where it fails at a very trivial part:
CREATE TABLE Enrollment (
CONSTRAINT class_id FOREIGN KEY (id) REFERENCES Class(id) NOT NULL,
CONSTRAINT member_id FOREIGN KEY (id) REFERENCES RecCenterMember(id) NOT NULL,
cost int NOT NULL
);
Then for that command I get this error:
CREATE TABLE Enrollment (
*
ERROR at line 1:
ORA-00904: : invalid identifier
How can I fix these two errors?
You need to create the column before you try creating constraints on the column.
You have:
CREATE TABLE Enrollment (
CONSTRAINT class_id FOREIGN KEY (id) REFERENCES Class(id) NOT NULL,
CONSTRAINT member_id FOREIGN KEY (id) REFERENCES RecCenterMember(id) NOT NULL,
cost int NOT NULL
);
You need:
CREATE TABLE Enrollment (
id INT NOT NULL CONSTRAINT class_id REFERENCES Class(id),
CONSTRAINT member_id FOREIGN KEY (id) REFERENCES RecCenterMember(id),
cost INT NOT NULL
);
Note that in the first line, the FOREIGN KEY isn't necessary because the column is implied. In the second line, the id is identified. You could also write:
CREATE TABLE Enrollment
(
id INT NOT NULL,
CONSTRAINT class_id FOREIGN KEY (id) REFERENCES Class(id),
CONSTRAINT member_id FOREIGN KEY (id) REFERENCES RecCenterMember(id),
cost INT NOT NULL
);
It is unusual, though not automatically wrong, to make a single column (id) be a foreign key of two tables simultaneously. It isn't clear if you actually want three columns in your table — and if you do, which column names are in your table.
You could also use the appropriate notation for an automatically allocated type in MySQL syntax (SERIAL instead of INT NOT NULL, or add AUTO_INCREMENT, etc).
Maybe you're really after:
CREATE TABLE Enrollment
(
id SERIAL,
class_id INT NOT NULL CONSTRAINT class_id REFERENCES Class(id),
member_id INT NOT NULL CONSTRAINT member_id REFERENCES RecCenterMember(id),
cost INT NOT NULL
);
This makes more sense in general. You're creating a new enrollment record for a pre-existing class, and for a pre-existing recreation centre member, and recording its cost.
Syntax diagrams vs actual behaviour
If, as Michael - sqlbot suggests — and I've no reason whatsoever to disbelieve him — MySQL recognizes but does not respond to the REFERENCES clause in a column definition in a CREATE TABLE statement but only acts on full FOREIGN KEY clauses, then you have to adjust my suggested answers from their syntactically correct but semantically ignored form to something like:
Option 1 (minimally changing the SQL from the question):
CREATE TABLE Enrollment (
id INT NOT NULL,
CONSTRAINT class_id FOREIGN KEY (id) REFERENCES Class(id),
CONSTRAINT member_id FOREIGN KEY (id) REFERENCES RecCenterMember(id),
cost int NOT NULL
);
Option 2 (what I consider the most plausible version):
CREATE TABLE Enrollment
(
id SERIAL,
class_id INT NOT NULL,
CONSTRAINT fk_class_id FOREIGN KEY (class_id) REFERENCES Class(id),
member_id INT NOT NULL,
CONSTRAINT fk_member_id FOREIGN KEY (member_id) REFERENCES RecCenterMember(id),
cost INT NOT NULL
);
Or some other variant of this syntax based on the desired table schema ignoring the FK constraints, then adding the constraints along the lines shown.
Key Point
You must define the columns before you define the foreign keys based on those columns.

Please assist me in locating my error in this MySQL code

I'm not sure what I'm doing wrong here, but I get an error:
Error Code: 1005. Can't create table 'erm.section' (emo:150)
Here is the code. The 'course' table is created successfully. I tried modifying the name of the course_number attritube in the 'section' table but that didn't work.
USE erm;
CREATE TABLE course
(
course_name VARCHAR(30) NOT NULL,
course_number VARCHAR(20) NOT NULL,
credit_hours INT NOT NULL,
department VARCHAR(10),
CONSTRAINT course_pk PRIMARY KEY (course_name)
);
CREATE TABLE section
(
section_identifier INT NOT NULL,
course_number VARCHAR(20),
semester VARCHAR(10) NOT NULL,
school_year VARCHAR(4) NOT NULL,
instructor VARCHAR(25),
CONSTRAINT section_pk PRIMARY KEY (section_identifier),
CONSTRAINT section_fk FOREIGN KEY (course_number)
REFERENCES course (course_number)
ON DELETE SET NULL
ON UPDATE CASCADE
);
course_number is not a primary key in the table course.
the foreign key in the table section must reference a primary key form another table.
You have to create an index on the column referenced by the foreign key:
alter table course add index (course_number);
(It doesn't have to be a primary key index.) From the MySQL documentation:
InnoDB permits a foreign key to reference any index column or group of
columns. However, in the referenced table, there must be an index
where the referenced columns are listed as the first columns in the
same order.
A FOREIGN KEY in one table points to a PRIMARY KEY in another table.
AFAIK, dropping the CONSTRAINT, then rename, then add the CONSTRAINT back is the only way. Backup first!
to drop it use this
ALTER TABLE section
DROP FOREIGN KEY course_number
and to add it again use this
ALTER TABLE section
ADD FOREIGN KEY (course_number)
REFERENCES course (course_number)