Add foreign key on delete cascade phpMyAdmin is not working - sql

I have a main table called book with fields id_book (primary, unique, auto increment) and name.
I have a secondary table called tag with fields book_id and tag
Each book can have many tags. I want that when I delete a book, all the tags to be deleted as well.
I tried this with this:
ALTER TABLE tag
ADD FOREIGN KEY (book_id)
REFERENCES book(id_book)
ON UPDATE CASCADE
ON DELETE CASCADE
I know I used this block of SQL in the past on some other project and it worked but now it seems it is not working anymore and I don't know why. If I delete a book, the tags will not be deleted.

I don't see any problem with the SQL in itself, i don't think the problem reside in this particular foreign key.
Maybe the key didn't register or another foreign key is blocking the delete.
I've tested with this SQL file and got the wanted results
CREATE TABLE book (
id_book INT AUTO_INCREMENT,
name VARCHAR(10),
PRIMARY KEY (id_book)
);
CREATE TABLE tag (
id INT AUTO_INCREMENT,
book_id INT,
name VARCHAR(10),
PRIMARY KEY (id)
);
ALTER TABLE tag
ADD FOREIGN KEY (book_id)
REFERENCES book(id_book)
ON UPDATE CASCADE
ON DELETE CASCADE;
INSERT INTO book (`name`) VALUES ("test", "another", "and another");
INSERT INTO tag (`book_id`, `name`) VALUES (1 , "first"), (2, "first"), (1, "second");

Related

Update or Delete Violates foreign key constraint

I have two tables that look like the following.
CREATE TABLE book (
book_id BIGSERIAL PRIMARY KEY,
book_special_id character(10) NOT NULL DEFAULT random_string(10) UNIQUE,
author_id bigint REFERENCES author(author_id) ON DELETE RESTRICT,
category_id bigint REFERENCES category(category_id) ON DELETE RESTRICT,
title text NOT NULL,
subtitle text,
book_text text
);
CREATE TABLE booksubcategory (
booksubcategory_id BIGSERIAL PRIMARY KEY,
book_id BIGSERIAL REFERENCES book(book_id) ON DELETE CASCADE,
subcategory_id BIGSERIAL REFERENCES subcategory(subcategory_id) ON DELETE RESTRICT,
CONSTRAINT booksubcategory_book_id_subcategory_id_key UNIQUE (book_id, subcategory_id)
);
In this example the book_id column is the primary key in the book table, and the referenced foreign key in the booksubcategory table. When I try and run the following sql, I receive the error:
ERROR: update or delete on table "book" violates foreign key constraint "booksubcategory_book_id_fkey" on table "booksubcategory"
Detail: Key (book_id)=(888392) is still referenced from table "booksubcategory"
Here is what the SQL looks like.
INSERT INTO book (book_special_id, author_id, category_id, title, subtitle, book_text)
VALUES ("D4jOko2IP0",34, 4, "Book Example", "Book Subtitle", "Some lengthy text")
ON CONFLICT (book_special_id)
DO UPDATE SET author_id=EXCLUDED.author_id, book_id=EXCLUDED.book_id, category_id=EXCLUDED.category_id, title=EXCLUDED.title, subtitle=EXCLUDED.subtitle, book_text=EXCLUDED.book_text;
In this situation the sql should update the columns because the book_special_key already exists in the book table.
I'm familiar with the reason why updates and deletes on foreign key constraints can fail for integrity reasons, but in my case I'm not updating the book_id directly, just the columns in the book table. Also I have ON DELETE CASCADE set on the foreign key in the child table. Can someone tell my why I'm experiencing this issue?
The inserted row clashes on unique key special_book_id, then the conflict rule tries to update the duplicate row.
But what is the value book_id of a NEW row that was not yet inserted due to conflicts and is autogen? Well, either null or a new serial.
So, whatever the case, you are updating book_id to null or a new serial and it fails as the old book_id value, that is disappearing, has references.
Remove the update to column book_id and it should work.

Postgresql, references to unique constraint

I'm running PostgreSQL 9.4 and have the following table:
CREATE TABLE user_cars (
user_id SERIAL REFERENCES users (id) ON DELETE CASCADE,
car CHARACTER VARYING(255) NOT NULL,
CONSTRAINT test UNIQUE (user_id, car)
);
The table allows a user to have multiple cars, but only use the car name once. But other users may have the same car name.
I would like to have another table with references to the unique constraint test, and have tried stuff like:
CREATE TABLE mappings (
other_id CHARACTER(9) REFERENCES other (id) ON DELETE CASCADE,
user_cars REFERENCES user_cards (test) ON DELETE CASCADE
);
But that fails "obviously". I would like to make sure that other_id only have a single references to a user_car entry.
So to explain, how can I in table mappings have a references to test from table user_cars.
This is the thing that fails currently:
user_cars REFERENCES user_cards (test) ON DELETE CASCADE
Don't use composite foreign key references, if you can avoid it. Just add a unique id to the table:
CREATE TABLE user_cars (
user_car_id serial primary key,
user_id int REFERENCES users (id) ON DELETE CASCADE,
car CHARACTER VARYING(255) NOT NULL,
CONSTRAINT test UNIQUE (user_id, car)
);
Then mappings is simply:
CREATE TABLE mappings (
mapping_id serial primary key,
user_car_id int references user_cars(user_car_id) on delete cascade,
other_id CHARACTER(9) REFERENCES other (id) ON DELETE CASCADE,
);
If car should be unique, add UNIQUE constrain only on car column.
If user should be unique, add UNIQUE constrain only on user column.
If you add UNIQUE constrain on combination, then there will be duplicate values in the table.
UPDATE:
You can add multiple constraints on single column. With Foreign key add UNIQUE constraint as well on user_cars column in mapping table.

Check if data exists in another table on insert?

Table A
(
Table_A_ID int
)
Table B
(
Table_B_ID int
Value int
)
Say I want to insert data into Table B, where 'Value' would be the same as a Table_A_ID.
How would I make a constraint or check that the data actually exists in the table on insertion?
You probably need to enforce data integrity not only on INSERT into Table B, but also on UPDATE and DELETE in both tables.
Anyway options are:
FOREIGN KEY CONSTRAINT on Table B
TRIGGERs on both tables
As a last resort if for some reason 1 and 2 is not an option STORED PROCEDUREs for all insert, delete update operations for both tables
The preferred way to go in most cases is FOREIGN KEY CONSTRAINT.
Yap, I agree with #peterm.
Cause, if your both Table_A_ID and Table_B_Id are primary keys for both tables, then you don't even need two tables to store the value. Since, your two tables are seems to be on 'one-to-one' relationship. It's one of the database integrity issues.
I think you didn't do proper normalisation for this database.
Just suggesting a good idea!
I found this example which demonstrates how to setup a foreign key constraint.
Create employee table
CREATE TABLE employee (
id smallint(5) unsigned NOT NULL,
firstname varchar(30),
lastname varchar(30),
birthdate date,
PRIMARY KEY (id),
KEY idx_lastname (lastname)
) ENGINE=InnoDB;
Create borrowed table
CREATE TABLE borrowed (
ref int(10) unsigned NOT NULL auto_increment,
employeeid smallint(5) unsigned NOT NULL,
book varchar(50),
PRIMARY KEY (ref)
) ENGINE=InnoDB;
Add a constraint to borrowed table
ALTER TABLE borrowed
ADD CONSTRAINT FK_borrowed
FOREIGN KEY (employeeid) REFERENCES employee(id)
ON UPDATE CASCADE
ON DELETE CASCADE;
NOTE: This tells MySQL that we want to alter the borrowed table by adding a constraint called ‘FK_borrowed’. The employeeid column will reference the id column in the employee table – in other words, an employee must exist before they can borrow a book.
The final two lines are perhaps the most interesting. They state that if an employee ID is updated or an employee is deleted, the changes should be applied to the borrowed table.
NOTE: See the above URL for more details, this is just an excerpt from that article!
Create a foreign key constraint on the column 'Value' on table B that references the 'Table_A_ID' column.
Doing this will only allow values that exist in table A to be added into the 'Value' field of table B.
To accomplish this you first need to make Table_A_ID column the primary key for table A, or it at least has to have some sort of unique constraint applied to it to be a foreign key candidate.
BEGIN TRANSACTION -- REMOVE TRANSACTION AND ROLLBACK AFTER DONE TESTING
--PUT A PRIMARY KEY ON TABLE A
CREATE TABLE A
( Table_A_ID int CONSTRAINT PK_A_Table_A_ID PRIMARY KEY)
--ON VALUE ADD A FOREIGN KEY CONSTRAINT THAT REFERENCEs TABLE A
CREATE TABLE B
( Table_B_ID int,
[Value] int CONSTRAINT FK_B_Value_A REFERENCES A(Table_A_ID)
)
-- TEST VALID INSERT
INSERT A (Table_A_ID) VALUES (1)
INSERT B (Table_B_ID, [Value]) VALUES (1,1)
--NOT ALLOW TO INSERT A VALUE THAT DOES NOT EXIST IN A
--THIS WILL THROW A FOREIGN KEY CONSTRAINT ERROR
INSERT B (Table_B_ID, [Value]) VALUES (1,2) -- 2 DNE in table A
ROLLBACK
Note: there is no magic to 'FK_B_Value_A' or 'PK_A_Table_A_ID' it simply a naming convention and be called anything. The syntax on the foreign key and primary key lines work like this:
column-definition CONSTRAINT give-the-constraint-a-name REFERENCES table-name ( table-column )
column-definition CONSTRAINT give-the-constraint-a-name PRIMARY KEY

Problem creating foreign keys in mySql

I created a foreign key in my sql by the following statemnt..
ALTER TABLE `users` ADD FOREIGN KEY ( `id`)
REFERENCES `user_login` (`user_id`)
ON DELETE CASCADE ;
The creation appears to succeed then after that I execute a delete statement
DELETE From user_login WHERE user_id = 1576;
yet in users the row still exists that is referencing that. I open up the mysql workbench and it doesn't show any signs that the foreign key was created. Does anyone know why this would be? Or what I am doing wrong? It is a one-to-one relationship in the two tables.
The table may be in MyISAM format, which does not support foreign keys.
Try converting it to InnoDB first:
alter table users engine=InnoDB;
You have to also make sure that both users.id and user_login.user_id have an index each.
Copy and paste this code in your Mysql script editor and run. You will have two tables categories and products these tables having cat_id as foreign key.
CREATE DATABASE IF NOT EXISTS dbdemo;
USE dbdemo;
CREATE TABLE categories(
cat_id int not null auto_increment primary key,
cat_name varchar(255) not null,
cat_description text
) ENGINE=InnoDB;
CREATE TABLE products(
prd_id int not null auto_increment primary key,
prd_name varchar(355) not null,
prd_price decimal,
cat_id int not null,
FOREIGN KEY fk_cat(cat_id)
REFERENCES categories(cat_id)
ON UPDATE CASCADE
ON DELETE RESTRICT
)ENGINE=InnoDB;

Foreign Key doesn't stop me entering data MySQL

I have a table which has one column as a foreign key joining to another table.
It's a cricket question where I have a table called Fixtures and another called Inning.
Inning table has a FixtureId column relates to the Fixture table.
I would expect that If i do a insert on the inning table using a FixtureId that doesn't relate to a Fixture then it would error but this isn't the case...
Can anyone explain why this is?
Make sure that you are using the InnoDB storage engine when creating the table. Other storage engines will simply ignore foreign key constraints. (Source)
Example:
CREATE TABLE a (
id INT AUTO_INCREMENT PRIMARY KEY
) ENGINE=INNODB;
CREATE TABLE b (
id INT AUTO_INCREMENT PRIMARY KEY,
a_id INT,
FOREIGN KEY (a_id) REFERENCES a(id)
) ENGINE=INNODB;
INSERT INTO b (id, a_id) VALUES(NULL, 1);
The above insert fails with:
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails...
im not sure i understand can you elaborate and show your sql statements?
if i understand correctly, ( which i may not ) your foreign key would just be blank if you did not have a value for that field, why would it error out?