Cannot add foreign keys to mapping tables - mysql

i cannot create foreign keys in my mapping table for a m:n-relation.
My Problem:
I work with the newest version of Shopware (Shopware 6 ) on a test machine and I want to develop a plugin which creates a custom entity. the creation proccess of my custom entity (table name: car) and the table proccess with the shopware migration works without problems. At the next step, I have created a mapping table (name: car_product) which handles the m:n-relation with the standard shopware "product"-Table.
At this point I cannot add my foreign keys which pointed to the product-table. There is no error during the execution process. The foreign Key to the car-table works fine.
I guess, my schema is not correct or a problem with the product-table is happen..
CREATE TABLE IF NOT EXISTS car (
`id_car` BINARY(16) NOT NULL,
`hsn` VARCHAR(3) NOT NULL,
`tsn` VARCHAR(4) NOT NULL,
`manufacturer` VARCHAR(45) NULL,
`model` VARCHAR(45) NULL,
`year` INT NULL,
`created_at` DATETIME(3) NOT NULL,
`updated_at` DATETIME(3) NULL,
PRIMARY KEY (`id_car`),
UNIQUE (`hsn`, `tsn`));
CREATE TABLE IF NOT EXISTS car_product(
`product_id` BINARY(16) NOT NULL,
`product_version_id` BINARY(16) NOT NULL ,
`id_car` binary(16) Not Null ,
PRIMARY KEY (`product_id`, `product_version_id`, `id_car`),
INDEX `fk_product_car_idx` (`id_car` ) ,
INDEX `fk_product_car_product_idx` (`product_id` , `product_version_id`) );
CREATE TABLE product (
id binary(16) ,
version_id binary(16),
...
cars binary(16),
)
The id, version_id attributes inside the product table are both the primaray key
SQL-Query to add the foreign Keys :
Alter Table `car_product` ADD FOREIGN KEY (`product_id`,`product_version_id`) REFERENCES `product` (`id`, `version_id`) ON DELETE CASCADE ON UPDATE CASCADE ;
Alter Table `car_product` ADD FOREIGN KEY (`id_car` ) REFERENCES `car` (`id_car`) ON DELETE CASCADE ON UPDATE CASCADE;

Related

mysql 8 (innodb) foreign key constraints on newly created indexes

Suppose I have a table items
with columns id (PRIMARY), name(VARCHAR), section_id (BIGINT), updated_at (DATETIME),
and a table sections with id (PRIMARY).
Naturally, items.section_id is a foreign key that refers to sections.id.
Suppose there is an index on items of the columns (section_id, name). I believe that if you tried to drop this index, you would get an error that it is needed in a foreign key constraint. I can accept this.
Now, I want to create a new index, like create index ix_section_id_id_updated_at on items (section_id, id, updated_at). MySQL lets me do this, but if I go to drop this table, I get that same error: it fails, because it is needed in a foreign key constraint.
Why should this be? It already has one index that can be used for this foreign key check. Further, the error does NOT go away with set FOREIGN_KEY_CHECKS=0;. Is there a way to force MySQL to not associate the new index with the foreign key, so that it is quick to drop? This is necessary because I will be running the migration on a production server with temporary downtime, and need to be able to quickly revert the migration in case of anything going wrong afterwards.
I can reproduce your issue if I don't create an index on section_id and allow mysql to do so on the creation of a foreign key(as described in the manual). Adding a new index drops the auto generated key and if you then drop the new index an error is generated because of the requirement to have a key , and mysql does not auto generate one on a drop.. . If you manually generate a key on section_id this problem does not happen..and the newly created compound index drops successfully.
drop table if exists items;
drop table if exists sections;
create table items(id int PRIMARY key, name varchar(3), section_id BIGINT, updated_at DATETIME);
create table sections(id bigint primary key);
alter table items
add foreign key fk1(section_id) references sections(id);
show create table items;
CREATE TABLE `items` ( `id` int(11) NOT NULL,
`name` varchar(3) DEFAULT NULL,
`section_id` bigint(20) DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk1` (`section_id`),
CONSTRAINT `fk1` FOREIGN KEY (`section_id`) REFERENCES `sections` (`id`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;
alter table items
add key key1(section_id, name);
show create table items;
CREATE TABLE `items` (
`id` int(11) NOT NULL,
`name` varchar(3) DEFAULT NULL,
`section_id` bigint(20) DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `key1` (`section_id`,`name`),
CONSTRAINT `fk1` FOREIGN KEY (`section_id`) REFERENCES `sections` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
and with manually generated key
drop table if exists items;
drop table if exists sections;
create table items(id int PRIMARY key, name varchar(3), section_id BIGINT, updated_at DATETIME);
create table sections(id bigint primary key);
alter table items
add key sid(section_id);
alter table items
add foreign key fk1(section_id) references sections(id);
show create table items;
CREATE TABLE `items` (
`id` int(11) NOT NULL,
`name` varchar(3) DEFAULT NULL,
`section_id` bigint(20) DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `sid` (`section_id`),
CONSTRAINT `fk1` FOREIGN KEY (`section_id`) REFERENCES `sections` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
alter table items
add key key1(section_id, name);
show create table items;
CREATE TABLE `items` (
`id` int(11) NOT NULL,
`name` varchar(3) DEFAULT NULL,
`section_id` bigint(20) DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `sid` (`section_id`),
KEY `key1` (`section_id`,`name`),
CONSTRAINT `fk1` FOREIGN KEY (`section_id`) REFERENCES `sections` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Not able to create table with foreign key constraints for two columns?

I have created below airports table :
CREATE TABLE airports(
airport_id int(4) unsigned AUTO_INCREMENT NOT NULL,
airport_name varchar(250),
primary key(airport_id)
)ENGINE=InnoDB;
But when I'm creating schedule table with foreign key constraints,Its not able to create. Below is the script :
CREATE TABLE schedule (
flight_id int(3) unsigned AUTO_INCREMENT NOT NULL,
origin_airport_id int(4),
destination_airport_id int(4) ,
departure_time char(15) not null,
arrival_time char(15) not null,
duration varchar(20) not null,
flight_fare decimal(9,2) not null,
PRIMARY KEY (flight_id),
FOREIGN KEY(origin_airport_id,destination_airport_id) REFERENCES airports(airport_id,airport_id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB;
Below is the error message from show 'engine innodb status;', when I try to create the schedule table.
Error in foreign key constraint of table airport_db/schedule:
FOREIGN KEY(origin_airport_id,destination_airport_id) REFERENCES airports(airport_id,airport_id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB:
Cannot find an index in the referenced table where the referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.
Note that the internal storage type of ENUM and SET changed in tables created with >= InnoDB-4.1.12, and such columns in old tables
cannot be referenced by such columns in new tables.
See http://dev.mysql.com/doc/refman/5.6/en/innodb-foreign- key-constraints.html for correct foreign key definition.
Foreign keys need to reference the primary (or unique) keys of a table. There are no duplicates. And, the types have to exactly match (int doesn't match int unsigned).
So, try this instead:
CREATE TABLE schedule (
flight_id int(3) unsigned AUTO_INCREMENT NOT NULL,
origin_airport_id int(4) unsigned,
destination_airport_id int(4) unsigned,
departure_time char(15) not null,
arrival_time char(15) not null,
duration varchar(20) not null,
flight_fare decimal(9,2) not null,
PRIMARY KEY (flight_id),
FOREIGN KEY(origin_airport_id) REFERENCES airports(airport_id) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY(destination_airport_id) REFERENCES airports(airport_id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB;
Here is a SQL Fiddle.

Can't Constrain Both Junction Table Columns

I have a juction table that contains two foreign keys (from Profiles and Districts tables), with both columns as a composite primary key.
`profID` int(11) NOT NULL,
`distID` varchar(8) NOT NULL,
PRIMARY KEY (`profID`,`distID`)
I'd like to constrain both columns, but MySql throws an error:
#1050 - Table './database_name/z#002dprof#002ddist' already exists
In troubleshooting the problem, I've tried creating another duplicate junction table from scratch, but I get the same error. Oddly, MySQL will allow me to constrain one column or the other, but not both columns. I'm stumped, since I have other (non-junction) tables that have constraints on more than one foriegn key column.
By the way, I'm using phpMyAdmin, and all tables are InnoDB with utf-8.
Any help would be appreciated.
ADDED: SHOW CREATE TABLE results
CREATE TABLE `Profiles` (
`profID` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(64) NOT NULL,
`stID` varchar(2) NOT NULL,
`zip` varchar(5) NOT NULL,
PRIMARY KEY (`profID`),
KEY `stID` (`stID`,`zip`),
KEY `email` (`email`)
) ENGINE=InnoDB AUTO_INCREMENT=52 DEFAULT CHARSET=utf8
CREATE TABLE `Districts` (
`distID` varchar(8) NOT NULL,
`stID` varchar(2) NOT NULL,
`abbrev` varchar(16) NOT NULL,
PRIMARY KEY (`distID`),
KEY `stID` (`stID`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8
CREATE TABLE `z-prof-dist` (
`profID` int(11) NOT NULL,
`distID` varchar(8) NOT NULL,
PRIMARY KEY (`profID`,`distID`),
KEY `distID` (`distID`),
KEY `profID` (`profID`),
CONSTRAINT `z-prof-dist_ibfk_1` FOREIGN KEY (`distID`) REFERENCES `Districts` (`distID`)
ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8
I think I found a fix. Rather than using the phpMyAdmin function for adding a constraint (where I kept getting the error message), I instead followed marekful's lead by using an SQL ALTER TABLE query (with a new constraint name) as such:
ALTER TABLE `z-prof-dist`
ADD CONSTRAINT `test1`
FOREIGN KEY (`profID`) REFERENCES `Profiles` (`profID`)
ON UPDATE CASCADE
I still don't understand the cause of the original error, but I can see that the newly added foreign key constraint is working perfectly.

On delete cascade not deleting the associates entries

I have a marks table which holds the foreign key to an associates message. I used ON DELETE with the expectation that deleting an entry in the marks table would also delete the associated message. It is not working as expected though. I checked out all the other post and can't find any relevant to this one.
I can insert into the database successfully
DELETE FROM marks WHERE x = 37.7836
but when I delete a mark the message that is associated with it is not deleted. Any insights as to what I am doing wrong here?
Edit:
Here is an image of me demonstrating my deletion process:
schema
DROP DATABASE uncovery;
CREATE DATABASE uncovery;
SET foreign_key_checks=0;
USE uncovery;
CREATE TABLE marks (
id int(5) AUTO_INCREMENT,
x float(10, 6),
y float(10, 6),
z float(10, 6),
timestamp timestamp DEFAULT CURRENT_TIMESTAMP,
messageId int(5),
FOREIGN KEY (messageId)
REFERENCES messages(id)
ON DELETE CASCADE,
PRIMARY KEY (id)
);
CREATE TABLE messages (
id int(5) AUTO_INCREMENT,
messageString text,
PRIMARY KEY (id)
);
EDIT 2: Schema Refactor
Here is my newly updated schema:
As you can see I am getting an error that this is invalid when I try to run it:
The foreign key as you've created it won't work the way you expect. Under your schema, if an entry is deleted from messages, it will delete all corresponding entries from the marks table, not the other way around.
Also, you must ensure that you are using the InnoDB storage engine for your tables, or your foreign keys won't work at all. They are not supported in the MyISAM engine type.
To get your schema working such that deleting a mark will cause a message to be deleted, you need to have a markId as a foreign key in the messages table, like so:
CREATE TABLE `messages` (
`id` int(5) NOT NULL auto_increment,
`messageString` text,
`markId` int(5) default NULL,
PRIMARY KEY (`id`),
KEY `markId` (`markId`),
CONSTRAINT `messages_ibfk_1` FOREIGN KEY (`markId`) REFERENCES `marks` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB;
CREATE TABLE `marks` (
`id` int(5) NOT NULL auto_increment,
`x` float(10,6) default NULL,
`y` float(10,6) default NULL,
`z` float(10,6) default NULL,
`timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;

Foreign Key not working: Error code 1005, SQL state HY000: Can't create table

I have two tables I have created and I'm adding the foreign key constraint after the fact.
The two tables are defined as such:
CREATE TABLE `user` (
`user_id` int(11) NOT NULL auto_increment,
`user_ad_id` varchar(500) default NULL,
`user_name` varchar(100) NOT NULL,
`login_id` varchar(100) default NULL,
`email` varchar(256) NOT NULL,
`personal_config` int(10) NOT NULL,
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
and
CREATE TABLE IF NOT EXISTS personal_config (
config_id INT(10) NOT NULL AUTO_INCREMENT,
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
configuration TEXT(25600) NOT NULL,
PRIMARY KEY (config_id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE personal_config ADD CONSTRAINT personal_config_fk_user FOREIGN KEY
(config_id) REFERENCES user(personal_config);
And I keep getting the same error but can't figure it out. I've searched all the related threads to this.
Your FK config_id can't be an autoincrement field, that doesn't make much sense right? That field reflects a value in the foreign table, it cannot be set arbitrarily in the local table.
I think this is what you want:
ALTER TABLE user ADD CONSTRAINT personal_config_fk_user FOREIGN KEY (personal_config) REFERENCES personal_config(config_id);
Your ALTER TABLE statement is backward. Since personal_config.config_id is an auto_increment primary key, the foreign key should be defined in the users table against personal_config, not in personal_config against the users table.
ALTER TABLE users ADD CONSTRAINT user_fk_personal_config
FOREIGN KEY (personal_config)
REFERENCES personal_config(config_id);
if you set your user table field personal_config is primary key then it is possible to execute
CREATE TABLE IF NOT EXISTS personal_config (
config_id INT(10) NOT NULL AUTO_INCREMENT,
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
configuration TEXT(25600) NOT NULL,
PRIMARY KEY (config_id), FOREIGN KEY
(config_id) REFERENCES user(personal_config)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;