Why can't I drop a foreign key? - mysql

Scenario:
Parent table | id primary key, message_p
Child table | id primary key, parent_id foreign key, message_c
I had 1 row of data in the parent table and 2 rows of data in the child table. I wanted to test constraints that an FK relationship enforces. I then attempted to remove the foreign key from the child table so that evene though the child table had 2 rows, I could then go ahead and remove the parent row:
alter table child
drop foreign key parent_id
I then got the following error:
[1091 - Can't DROP 'parent_id'; check that column/key exists]
Notes:
show create table child
CREATE TABLE `track` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`member_id` int(11) NOT NULL,
`title` varchar(50) DEFAULT NULL,
`artist` varchar(50) DEFAULT 'TBA',
`album` varchar(50) DEFAULT 'TBA',
`genre` varchar(50) DEFAULT 'TBA',
`dance_style` varchar(50) DEFAULT 'TBA',
PRIMARY KEY (`id`),
KEY `member_id` (`member_id`),
CONSTRAINT `track_ibfk_1` FOREIGN KEY (`member_id`) REFERENCES `member` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Am I missing something in my query or the general understanding about FK's?

You are trying to delete the Foreign Key Constraint by column name, that's why your code doesn't work.
First query your foreign key constraint name (using show create table child as you did show the key name, something like track_ibfk_1

If you tried out everything as commented (assuming correct table names, constraint names, ...), I see no reason why it should not work.
If you have, however, other tables that hold foreign keys to parent (or 'member'), maybe that these constraints block removal of parent entries?
Anyway, here is an example showing that dropping a foreign key actually works:
drop table if exists testchild;
drop table if exists test;
create table test(
id int primary key,
name varchar(50)
);
create table testchild(
childid int primary key,
reftotest int,
constraint reftotest_FK foreign key (reftotest) references test(id)
);
insert into test values (1, 'Jack'), (2, 'Sam');
insert into testchild values (1, 1), (2, 2), (3, 1);
insert into testchild values (4,5); # will fail
delete from test where id = 1; # will fail
alter table testchild drop foreign key reftotest_FK;
insert into testchild values (4,5); # will not fail any more
delete from test where id = 1; # will not fail any more

Related

MySQL Error 1452 when adding data to tables

I get the following error when trying to import data via MySQL Workbench:
Preparing...
Importing DataInputs.sql...
Finished executing script
ERROR 1452 (23000) at line 6: Cannot add or update a child row: a foreign key constraint fails (`nsldatabase`.`player`, CONSTRAINT `playsFor` FOREIGN KEY (`player_ID`) REFERENCES `team` (`team_ID`))
Operation failed with exitcode 1
I am creating the database via two different SQL scripts. One creates the tables, and another imports the data. I thought initially that some foreign key wasn't define properly, but it seems like they are all setup properly. Any help would be great. See both files below:
This is the NSLStructure.sql file:
DROP DATABASE IF EXISTS NSLdatabase;
CREATE SCHEMA IF NOT EXISTS NSLdatabase;
USE NSLdatabase;
CREATE TABLE player (
player_ID int NOT NULL,
player_Name text NOT NULL,
player_Position text NOT NULL,
player_Skills int NOT NULL,
team_ID int NOT NULL,
CONSTRAINT playerPK PRIMARY KEY (player_ID)
);
CREATE TABLE history (
history_ID int NOT NULL,
player_ID int NOT NULL,
history_Desc text NOT NULL,
history_sDate text NOT NULL,
history_eDate text NOT NULL,
CONSTRAINT recordPK PRIMARY KEY (history_ID, player_ID)
);
CREATE TABLE field (
field_ID int NOT NULL,
field_Name text NOT NULL,
field_Location text NOT NULL,
CONSTRAINT fieldPK PRIMARY KEY (field_ID)
);
CREATE TABLE team (
team_ID int NOT NULL,
team_Name text NOT NULL,
team_City text NOT NULL,
field_ID int NOT NULL,
captain_ID int NOT NULL,
team_coach text NOT NULL,
CONSTRAINT teamPK PRIMARY KEY (team_ID)
);
CREATE TABLE matches (
matches_ID int NOT NULL,
matches_Date text NOT NULL,
matches_Score text NOT NULL,
matches_Winner text NOT NULL,
field_ID int NOT NULL,
teamHost_ID int NOT NULL,
teamGuest_ID int NOT NULL,
CONSTRAINT matchesPK PRIMARY KEY (matches_ID)
);
CREATE TABLE goal (
goal_ID int NOT NULL,
goal_Time int NOT NULL,
matches_ID int NOT NULL,
player_ID int NOT NULL,
CONSTRAINT goalPK PRIMARY KEY (goal_ID, matches_ID, player_ID)
);
ALTER TABLE team
ADD CONSTRAINT capitanRel FOREIGN KEY (captain_ID)
REFERENCES player (player_ID);
ALTER TABLE team
ADD CONSTRAINT playedOnField FOREIGN KEY (field_ID)
REFERENCES field (field_ID);
ALTER TABLE player
ADD CONSTRAINT playsFor FOREIGN KEY (player_ID)
REFERENCES team (team_ID);
ALTER TABLE history
ADD CONSTRAINT hasRel FOREIGN KEY (player_ID)
REFERENCES player (player_ID);
ALTER TABLE goal
ADD CONSTRAINT scoredBy FOREIGN KEY (player_ID)
REFERENCES player (player_ID);
ALTER TABLE goal
ADD CONSTRAINT scoredIn FOREIGN KEY (matches_ID)
REFERENCES matches (matches_ID);
ALTER TABLE matches
ADD CONSTRAINT playedOn FOREIGN KEY (field_ID)
REFERENCES field (field_ID);
ALTER TABLE matches
ADD CONSTRAINT playedHost FOREIGN KEY (teamHost_ID)
REFERENCES team (team_ID);
ALTER TABLE matches
ADD CONSTRAINT playedGuest FOREIGN KEY (teamGuest_ID)
REFERENCES team (team_ID);
This is the DataInputs.sql file:
USE NSLdatabase;
INSERT INTO player
VALUES
(1, "Paxton Pomykal", "Midfielder", 7.5, 1);
INSERT INTO history
VALUES
(1, 3, "US 20 Squad", "11/27/2003", "12/19/2003");
INSERT INTO field
VALUES
(1, "Dicks Sporting Goods Park", "Commerce City, CO");
INSERT INTO team
VALUES
(2, "Colorado Rapids", "Denver, CO", 1, 3, "Robin Fraser");
INSERT INTO matches
VALUES
(1, "01/08/2019", "0-1", 2, 1, 1, 2);
INSERT INTO goal
VALUES
(1, 32, 1, 19);
You are not inserting the data in the correct sequence. Parent rows need to be created before children rows, so the foreign key constraints are not violated.
So, typically, you need to create rows in team rows before creating rows in player. There may be other dependencies that you need to look into, based on the same logic.
An alternative approach would be to add the foreign key constraints after the data is inserted. However, I would not necessarily recommend that: if your data has invalid relationships, you will not be able to create the foreign keys. It is safer to proceed the other way around, since offending rows are immediately signaled.

How to rename both a primary key and a foreign key connected with each other?

I created two tables and want to set a one_to_many relation.
I firstly created a primary key tappa_id on table 'tappa' and then a foreign key tappa_id connected to the previous one on table low_cost_hotels.
I then changed the name of the table tappa to leg.
I want to rename the primary key in the first table and the foreign key in the second one which refers to it but I always get errors. I wonder whether or not the issue is due to the fact that they're already connected with each other:
I wrote the following code to drop the primary key in the table legs-->
ALTER TABLE legs DROP COLUMN tappa_id ;
And got this error message (FrancigenaApp is the name of the database which contains the tables) ->
ERROR 1025 (HY000): Error on rename of './FrancigenaApp/#sql-33c0_26' to './FrancigenaApp/legs' (errno: 150)
I wrote the following code to drop the foreign key connected to the previous (tappa_id) in the table low_cost_hotels:
ALTER TABLE low_cost_hotels DROP FOREIGN KEY tappa_id;
and got the error:
ERROR 1025 (HY000): Error on rename of './FrancigenaApp/low_cost_hotels' to
'./FrancigenaApp/#sql2-33c0-27' (errno: 152)
I suppose I need to drop the foreign key before renaming the primary key but I can't do that and it doesn't seem to be an error in the SQL syntax...
This works for me, even without disabling foreign key checks:
Initial schema:
create table parent (
parent_id int,
data text,
primary key (parent_id)
);
create table child (
child_id int,
parent_id int,
data text,
primary key (child_id),
foreign key (parent_id) references parent(parent_id)
);
insert into parent (parent_id, data) values (1, 'data');
insert into child (child_id, parent_id, data) values (1, 1, 'data');
Rename parent_id to parent_id_new in both tables;
alter table child change parent_id parent_id_new int;
alter table parent change parent_id parent_id_new int;
Check the schema:
show create table parent;
show create table child;
Result is:
CREATE TABLE `parent` (
`parent_id_new` int(11) NOT NULL,
`data` text,
PRIMARY KEY (`parent_id_new`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
CREATE TABLE `child` (
`child_id` int(11) NOT NULL,
`parent_id_new` int(11) DEFAULT NULL,
`data` text,
PRIMARY KEY (`child_id`),
KEY `parent_id` (`parent_id_new`),
CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id_new`) REFERENCES `parent` (`parent_id_new`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
View on DB Fiddle
In MySQL 8 you can use RENAME COLUMN syntax:
alter table child rename column parent_id to parent_id_new;
alter table parent rename column parent_id to parent_id_new;

MySQL - Update cell value using foreign key

I've got a problem creating a database.
I'd like to update children table using it's foreign key referencing to mother table automatically.
It means that when data values are inserted into the mother table, the children table gets updated on the column that is the foreign key.
Here's the code i wrote:
drop database domowa_biblioteka;
create database domowa_biblioteka;
use domowa_biblioteka;
create table pozycje
(
lp_p mediumint NOT NULL auto_increment,
nazwisko_autora char(30),
tytul char(60),
ilosc_stron int(4),
cena_oryginalna int(4),
na_sprzedaz enum('NIE','TAK'),
sprzedana enum('NIE','TAK'),
nr_pokoju mediumint,
PRIMARY KEY (lp_p)
)
;
create table kod_miedzynarodowy
(
lp_km mediumint,
ISBN char(20),
FOREIGN KEY (lp_km) REFERENCES pozycje (lp_p)
ON UPDATE CASCADE
)
;
create table pokoje
(
nr_pokoju mediumint NOT NULL auto_increment,
opis char(30),
PRIMARY KEY (nr_pokoju)
)
;
alter table pozycje ADD FOREIGN KEY (nr_pokoju) REFERENCES pokoje (nr_pokoju);
The thing is that the values of columns remain NULL after inserting data to rows.
Thanks for help!

Foregin keys returns empty results

I'm using an a mySQL db on localhosts. Created table with primary key and another table with foreign key pointing to that one, but when I want to see the results all I geted is "alert" that MySQL returned emty result. Here my tables
CREATE TABLE example_1(
ex1_id int NOT NULL AUTO_INCREMENT,
first_name varchar(50) NULL,
last_name varchar(50) NULL,
CONSTRAINT example_1_pk PRIMARY KEY (ex1_id)
);
CREATE TABLE example_2 (
ex2_id int NOT NULL AUTO_INCREMENT,
acces_lvl int NOT NULL,
CONSTRAINT example_2_pk PRIMARY KEY (ex2_id)
);
CREATE TABLE example_3 (
ex3_id int NOT NULL AUTO_INCREMENT,
first int NOT NULL,
second int NOT NULL,
CONSTRAINT example_3_pk PRIMARY KEY (ex3_id),
FOREIGN KEY (first) REFERENCES example_1(ex1_id),
FOREIGN KEY (second) REFERENCES example_2(ex2_id)
);
Then I add something to db, eg.
INSERT INTO `example_1`(`first_name`, `last_name`) VALUES ('foo', 'bar');
and
INSERT INTO `example_2`(`acces_lvl`) VALUES (2)
then when I try
SELECT * FROM `example_3`
I have nothing, empty results. Shouldn't be there id's from other tables? Am I doing something wrong, or I didn't do something? I'm totally noob in database.
Because you did not insert any data into example_3. Foreign key constraints don't propagate data, they just enforce the data relationship, so when you do insert data into example_3, the values you put in the columns with foreign key constraints have corresponding values in other table.

FOREIGN KEY references same table's column. Can't insert values

I created table with FOREIGN KEY and can't insert anything.
CREATE TABLE menus (
id int(10),
parent_id int(10),
label varchar(255),
PRIMARY KEY (id),
FOREIGN KEY (parent_id) REFERENCES menus (id)
);
I need FOREIGN KEY to automatically delete children when parent was deleted. This table was successfully created but I can't insert anything.
INSERT INTO `menus` (`parent_id`, `label`)
VALUES ('1', 'label1');
or
INSERT INTO `menus` (`label`)
VALUES ( 'label1');
#1452 - Cannot add or update a child row: a foreign key constraint fails
I really don't want look for any children in php code so I need somehow create simple table with 3 columns and automatically drop all children and they children too.
For all your needs you should take this structure
CREATE TABLE `menus` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`parent_id` int(11) unsigned DEFAULT NULL,
`label` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `fk_parent_menu` (`parent_id`),
CONSTRAINT `fk_parent_menu` FOREIGN KEY (`parent_id`)
REFERENCES `menus` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
);
SQL Fiddle DEMO
Demo shows inserting and deleting of a parent node
The magic drop part for all children is done by ON DELETE CASCADE
Typically, you will need to allow the 'root' record to have a null parent - i.e. menus.parent_id should be nullable, and the 'root' menu item will have a null parent_id.
i.e.
Change your DDL to:
parent_id int(10) NULL
And then you add your root element with NULL as the parent_id
insert into `menus` (id, `label`, parent_id)
VALUES (1, 'label1', null);
Then you are good to go with child elements:
insert into `menus` (id, `label`, parent_id)
VALUES (2, 'subitem1', 1);
etc.
SQL Fiddle here