I created two tables in mysql,
customer
house table with houseID being foreign key in my customer table.
Create customer table(
id int not null primary key auto_increment,
name varchar not null,
houseId int not null,
telephoneNo, int not null,
CONSTRAINT FOREIGN KEY (houseId) REFERENCES house(id) ON DELETE CASCADE);
CREATE house table(id int not null primary key auto_increment,
houseNo int not null,
address varchar not null);
However, when I delete customer with a specific houseId, the row in house table doesn't get deleted though I put on delete cascade in the customer table. Any idea why?
Your foreign key is on the wrong table. The way you got it set up is that if you delete a house, the corresponding cutomer will be cascaded.
You will want to put a customerId foreign key in the house table and have ON DELETE CASCADE foreign key trigger from side.
With a foreign key the ON DELETE is asking: what if the foreign key I am referencing is deleted (cascade, set null, do nothing)? not what to do when this row get's deleted.
Related
I keep getting this error when attempting to create a table with SQL.
I have these two tables:
I'm using PHPMyAdmin and it won't allow me to use M_id as a foreign key which references Employee Table primary key E_id.
Anyone able to see what's wrong with my code?
Thanks!
Foreign key definitions have to exactly match the primary key columns to which they refer. In this case, you defined Department.M_id to a be a nullable integer column, while EMPLOYEE.E_id is integer not nullable. Try making M_id not nullable:
CREATE TABLE Department (
D_name VARCHAR(100) NOT NULL,
D_id INT NOT NULL,
M_id INT NOT NULL DEFAULT 0000,
...
FOREIGN KEY (M_id) REFERENCES EMPLOYEE(E_id)
ON DELETE SET DEFAULT ON UPDATE CASCADE
)
Your code has multiple errors:
varchar() length is too long.
You have a forward reference for a foreign key constraint.
SET DEFAULT doesn't really work.
You want something like this:
CREATE TABLE employees (
employee_id int not null primary key,
Job_type VARCHAR(100),
Ssn INT NOT NULL,
Salary DECIMAL NOT NULL,
Address VARCHAR(500) NOT NULL,
First_name VARCHAR(50) NOT NULL,
M_initial CHAR(1),
Last_name VARCHAR(50) NOT NULL,
E_end_date DATE,
E_start_date DATE NOT NULL,
department_id INT NOT NULL,
Super_id INT,
FOREIGN KEY (Super_id) REFERENCES employees(employee_id) ON DELETE SET NULL ON UPDATE CASCADE,
UNIQUE (Ssn)
);
CREATE TABLE departments (
department_id int primary key,
D_name VARCHAR(100) NOT NULL,
D_id INT NOT NULL,
M_id INT DEFAULT 0000,
Manager_start_date DATE NOT NULL,
Manager_end_date DATE,
Report VARCHAR(8000),
Num_of_employees INT NOT NULL,
FOREIGN KEY (M_id) REFERENCES employees(employee_id) ON DELETE SET NULL ON UPDATE CASCADE,
UNIQUE (D_name)
);
ALTER TABLE employees ADD CONSTRAINT FOREIGN KEY (department_id) REFERENCES departments(department_id)
ON DELETE CASCADE ON UPDATE CASCADE;
I also changed a few other things:
The table names are plural.
The primary keys are the singular form followed by "_id".
Foreign keys and primary keys have the same name.
The primary key is the first column in the table.
Here is a db<>fiddle showing that this works.
I will not question your design, though it looks problematic.
However - You cannot reference a table which doesn't exist yet (REFERENCES Department(D_id)). You should either remove the FOREIGN KEY constraints from the CREATE statements and add them afterwards in ALTER TABLE statements.
Example:
CREATE TABLE EMPLOYEE (...);
CREATE TABLE Department (...);
ALTER TABLE EMPLOYEE
ADD FOREIGN KEY (D_id)
REFERENCES Department(D_id)
ON DELETE CASCADE
ON UPDATE CASCADE
;
Demo
Or temporarily disable foreign key checks:
SET FOREIGN_KEY_CHECKS = 0;
CREATE TABLE EMPLOYEE (...);
CREATE TABLE Department (...);
SET FOREIGN_KEY_CHECKS = 1;
Demo
You can also not use ON DELETE SET DEFAULT. InnoDB doesn't support it. You need to change it to ON DELETE SET NULL. If you want that behavior, you will need to implement it either in your application code or in a trigger.
I would also use TEXT as data type instead of VARCHAR(30000).
I created two tables students and orders, I tried to add a foreign key to the table "orders" but i have this error :
Cannot add or update a child row: a foreign key constraint fails
table STUDENTS:
CREATE TABLE STUDENTS (
ID varchar(50) NOT NULL,
NAME VARCHAR (20) NOT NULL,
AGE INT NOT NULL,
ADDRESS CHAR (25),
PRIMARY KEY (ID)
)
Table ORDERS
CREATE TABLE Orders
(O_Id int NOT NULL PRIMAY KEY,
Order_No int NOT NULL,ID varchar(50))
Add foreign key to "orders":
ALTER TABLE Orders
ADD CONSTRAINT fk_PerOrders
FOREIGN KEY(ID)
REFERENCES STUDENTS (ID)
Check if [Orders] table currently has any IDs that are not in [STUDENTS] table.
I think that you are trying to add foreign key constraint and there is no corresponding primery key in parent table.
Try to run
SET FOREIGN_KEY_CHECKS=0
your ALTER TABLE statement. When you finish run
SET FOREIGN_KEY_CHECKS=1
I created two tables students and orders and I added a foreign key constraint to the order table but I forgot to add on delete cascade option to this table.
table STUDENTS:
CREATE TABLE STUDENTS (
ID varchar(50) NOT NULL,
NAME VARCHAR (20) NOT NULL,
AGE INT NOT NULL,
ADDRESS CHAR (25),
PRIMARY KEY (ID)
)
Table ORDERS
CREATE TABLE Orders
(O_Id int NOT NULL PRIMAY KEY,
Order_No int NOT NULL,ID varchar(50))
Add foreign key to "orders":
ALTER TABLE Orders
ADD CONSTRAINT fk_PerOrders
FOREIGN KEY(ID)
REFERENCES STUDENTS (ID)
I tried this attempt :
ALTER TABLE Orders
ADD CONSTRAINT fk_PerOrders
FOREIGN KEY(ID)
REFERENCES STUDENTS (ID) ON DELETE CASCADE
Thanks.
You have a typo in the Order table. You have PRIMAY where it should be PRIMARY.
After correcting this, I tried creating the tables and all statements worked fine, including the last one.
I have posted this code in another threat, but this question is slightly different. I have to make a trigger. The question sounds like this:
"Create a trigger that removes the season if unused whenever
information about when and who produces a product is deleted (i.e.,
whenever a record is removed from the 'Produces' table, check if there
are other records about product being produced for the same season, if
not, remove also the corresponding record from the season table)"
My MYSQL code:
the MYSQL code is here:
CREATE TABLE IF NOT EXISTS Dvds(
Serial integer NOT NULL,
Name varchar(50),
Year integer,
Genre varchar(50),
Price integer,
PRIMARY KEY (Serial));
CREATE TABLE IF NOT EXISTS Shops(
Id integer NOT NULL,
Name varchar(50),
Address varchar(50),
PRIMARY KEY (Id));
CREATE TABLE IF NOT EXISTS Customers(
CNo integer NOT NULL,
AccNo integer,
Time varchar(50),
PRIMARY KEY (CNo));
CREATE TABLE IF NOT EXISTS ContactPersons(
Id integer NOT NULL,
Name varchar(50),
Phone integer,
PRIMARY KEY (Id));
CREATE TABLE IF NOT EXISTS Seasons(
StartDate date NOT NULL,
EndDate date NOT NULL,
PRIMARY KEY (StartDate,EndDate));
CREATE TABLE IF NOT EXISTS WebShops(
Id integer NOT NULL,
Url varchar(50),
FOREIGN KEY (Id) REFERENCES Shops (Id),
PRIMARY KEY (Id));
CREATE TABLE IF NOT EXISTS Producer(
Id integer NOT NULL,
Address varchar(50),
Name varchar(50),
PRIMARY KEY (Id));
CREATE TABLE IF NOT EXISTS Sold(
Id integer NOT NULL,
CNo integer NOT NULL,
Serial integer NOT NULL,
FOREIGN KEY (Id) REFERENCES Shops (Id),
FOREIGN KEY (CNo) REFERENCES Customers (CNo),
FOREIGN KEY (Serial) REFERENCES Dvds (Serial),
PRIMARY KEY (Id,CNo,Serial));
CREATE TABLE IF NOT EXISTS Has(
Id integer NOT NULL,
Serial integer NOT NULL,
FOREIGN KEY (Id) REFERENCES Shops (Id),
FOREIGN KEY (Serial) REFERENCES Dvds (Serial),
PRIMARY KEY (Id,Serial));
CREATE TABLE IF NOT EXISTS Has2(
Serial integer NOT NULL,
Producer_Id integer NOT NULL,
StartDate date NOT NULL,
EndDate date NOT NULL,
ContactPersons_Id integer NOT NULL,
FOREIGN KEY (Serial) REFERENCES Dvds (Serial),
FOREIGN KEY ( Producer_Id) REFERENCES Producer (Id),
FOREIGN KEY (StartDate) REFERENCES Seasons (StartDate),
FOREIGN KEY (EndDate) REFERENCES Seasons (EndDate),
FOREIGN KEY (ContactPersons_Id) REFERENCES ContactPersons (Id),
PRIMARY KEY (Serial,Producer_Id,StartDate,EndDate,ContactPersons_Id));
The trigger:
CREATE TRIGGER `Seasons_before_delete`
AFTER DELETE ON `Seasons`
FOR EACH ROW
BEGIN
DELETE FROM seasonstart
WHERE seasonstart.???????
DELETE FROM seasonend
WHERE seasonend.??????
END
but I really don't know. My teacher told me that I could use IF , ELSEIF, GOTOEND? But am i on the right track? I'm really blank right now what to do, so hope someone have a suggestion, what I could do to solve this?
In a trigger you have 2 virtual tables.
NEW and OLD.
Obviously in a create trigger there is no old and in a delete trigger there is no new.
So if you want to use the data of the table where the change happened (the table the trigger is attached to) you use those two tables.
Because this is a delete trigger you'll need to use the old table.
So your trigger will look something like this:
CREATE TRIGGER `Seasons_before_delete` AFTER DELETE ON `Seasons`
FOR EACH ROW
BEGIN
DELETE FROM seasonstart
WHERE seasonstart.seasonID = old.ID
DELETE FROM seasonend
WHERE seasonend.seasonID = old.ID
END
Note that it makes little sense to call a AFTER DELETE trigger "something_something_BEFORE" :-).
Further note that I have no idea why you need an IF in this trigger, the where in the delete statement already takes care of that.
In database design, can 2 entities have 2 relationships among themselves? i.e for example there are 2 entities donor and admin.. there are 2 relationships
1. admin accesses donor details
2. admin can contact donor and vice versa
can we join them with 2 relationships?
Definitely, although how much sense it makes to model "accesses" and "contacts" relations in a database depends on your application. I'll stay with your example though and assume these relations are n to n. Here is how the SQL could look like (warning, syntax not tested):
CREATE TABLE admin (
id int unsigned AUTO_INCREMENT PRIMARY KEY,
name text NOT NULL
);
CREATE TABLE donor (
id int unsigned AUTO_INCREMENT PRIMARY KEY,
name text NOT NULL
);
CREATE TABLE admin_donor_access_details (
id_admin int unsigned NOT NULL,
id_donor int unsigned NOT NULL,
PRIMARY KEY (id_admin, id_donor),
CONSTRAINT FOREIGN KEY(id_admin) REFERENCES admin(id) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT FOREIGN KEY(id_donor) REFERENCES donor(id) ON DELETE CASCADE ON UPDATE CASCADE
);
CREATE TABLE admin_donor_contact (
id_admin int unsigned NOT NULL,
id_donor int unsigned NOT NULL,
PRIMARY KEY (id_admin, id_donor),
CONSTRAINT FOREIGN KEY(id_admin) REFERENCES admin(id) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT FOREIGN KEY(id_donor) REFERENCES donor(id) ON DELETE CASCADE ON UPDATE CASCADE
);
The two relations could also be expressed in a single join table with boolean flags, like this:
CREATE TABLE admin_donor (
id_admin int unsigned NOT NULL,
id_donor int unsigned NOT NULL,
detail_access tinyint(1) NOT NULL,
contact tinyint(1) NOT NULL,
PRIMARY KEY (id_admin, id_donor),
CONSTRAINT FOREIGN KEY(id_admin) REFERENCES admin(id) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT FOREIGN KEY(id_donor) REFERENCES donor(id) ON DELETE CASCADE ON UPDATE CASCADE
);
This will put some extra effort on your code because you need to determine whether to insert or update a row when adding a relationship, and whether to delete or update a row when removing a relationship, but in my opinion this is still a usable alternative.