foreign key constraint on update cascade on delete cascade - mysql

I have two tables: one and two. I have a primary key (id) in table one.
Table One:
CREATE TABLE `one` (
`id` int(20) NOT NULL AUTO_INCREMENT,
`first_name` varchar(10) NOT NULL,
`last_name` varchar(10) NOT NULL,
`salary` int(100) NOT NULL,
`login_date_time` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1
id first_name last_name salary login_date_time
Table Two
CREATE TABLE two AS (SELECT id,salary ,CONCAT(first_name, ',', last_name) AS Name from one)
Now adding the foreign key to id as:
ALTER TABLE two
ADD CONSTRAINT `0_38775` FOREIGN KEY (id)
REFERENCES one(id) ON DELETE CASCADE ON UPDATE CASCADE
the table two comes as with the values from table one:
id salary name
Now to maintain referential integrity, how to update the values of table two when table one is updated. And also I cannot delete rows from table one and cannot insert rows to table two.
How can I update all the columns of table two when table one is updated/inserted. or insert explicitly into table two

Well, for the case of delete, when you delete the row from table 1, all the rows corresponding to that id will be deleted from table 2.
In case of update, if you want first name and last name to be updated in table 2 when they are altered in table 1 then you will have to write an update trigger for that.

Related

How to add columns from one MySQL table to another without duplicates?

There are two tables. It is necessary to insert two fields from one to the other so that duplicates do not appear. I tried those methods that are described for
USING INSERT IGNORE
Using replace
USING INSERT ... on duplicate key update
But I didn't succeed. For example, it ignore duplicate and write these:
REPLACE INTO user_favorites
(user_id, partner_id)
SELECT id, partner_id FROM users
How to do it?
1 table
create table local.users
(
id int auto_increment,
name varchar(255) null,
email varchar(255) null,
password varchar(255) null,
partner_id int null,
constraint users_email_unique
unique (email),
constraint users_id_uindex
unique (id)
)
alter table local.users
add primary key (id);
2 table
create table local.user_favorites
(
id int auto_increment,
user_id int null,
partner_id int null,
constraint user_favorites_id_uindex
unique (id),
constraint user_favorites_partners_id_fk
foreign key (partner_id) references local.partners (id)
on update cascade on delete cascade,
constraint user_favorites_users_id_fk
foreign key (user_id) references local.users (id)
on update cascade on delete cascade
);
alter table local.user_favorites
add primary key (id);
insert ignore and insert ... on duplicate key and replace all detect duplicates by whatever unique key constraints you have. Right now, your only unique constraint in user_favorites is the primary key id, which obviously doesn't help.
Add a unique constraint on user_id and partner_id:
alter table local.user_favorites add unique (user_id,partner_id);
If that fails, you already have duplicates that you will need to clean up first.
Then do any of the things you tried to add the rows from users.
You can first add empty columns and then update corresponding values by join operation. Like this:
ALTER TABLE user_favorites ADD COLUMN
name VARCHAR(255) NULL,
email VARCHAR(255) NULL,
password VARCHAR(255) NULL;
CONSTRAINT users_email_unique UNIQUE(email);
UPDATE user_favorites tb1
INNER JOIN users tb2 ON tb1.user_id = tb2.id
AND tb1.partner_id = tb2.partner_id
SET tb1.name = tb2.name
tb1.email = tb2.email
tb1.password = tb2.password;
Reference here: https://www.tutorialspoint.com/can-we-add-a-column-to-a-table-from-another-table-in-mysql

Add a Foreign Key to a Populated MYSQL table

I need to add a foreign key to a table already populated with data ...
CREATE TABLE `clientes` (
`id_cliente` int(11) NOT NULL,
`id_cashback` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `cashback00` (
`id` int(11) NOT NULL,
`valor` decimal(9,2) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
ALTER TABLE clientes ADD CONSTRAINT fk_cliente_cashback FOREIGN KEY (id_cashback) REFERENCES cashback(id)
ALTER TABLE only works if the parent table (customers) is not populated.
If it already has data, how to proceed since ALTER TABLE presents error "error no. 150" Foreign key constraint is incorrectly formed "
The problem is not that the table is populated with data.
The problem is that the column you are referencing, cashback(id), is not the key of that table.
To make a foreign key, the column you reference should be the primary key of the referenced table.
So I reckon you must first do this:
ALTER TABLE cashback00 ADD PRIMARY KEY (id);
But that will not work if you have duplicate values in id. The primary key must be unique.
Also your foreign key needs to reference the table name you used cashback00, not cashback. Unless you also have a table named cashback which you have not shown in your question.
Thanks to everyone for your help, but I managed to solve the problem:
SGBD integrity issue ...
see, if you want to add a foreign key to a populated parent table, the column must also be populated, like this:
UPDATE clientes
SET id_cashback = '1'
WHERE id_cliente >= '1' AND id_cliente <= '3500'
INSERT INTO cashback00 (valor) VALUES (10.00)
ALTER TABLE clientes ADD CONSTRAINT fk_cliente_cashback FOREIGN KEY (id_cashback) REFERENCES cashback(id)

How to migrate IDs from JOIN table into foreign key column in MySQL

I have the following tables in my MySQL database:
CREATE TABLE `User` (
`id` char(25) CHARACTER SET utf8 NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `email_UNIQUE` (`email`(191))
);
CREATE TABLE `Post` (
`id` char(25) NOT NULL,
`authorId` char(25) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `authorId` (`authorId`),
CONSTRAINT `Post_ibfk_1` FOREIGN KEY (`authorId`) REFERENCES `User` (`id`)
);
CREATE TABLE `_PostToUser` (
`A` char(25) CHARACTER SET utf8 NOT NULL,
`B` char(25) CHARACTER SET utf8 NOT NULL,
UNIQUE KEY `PostToUser_AB_unique` (`A`,`B`),
KEY `B` (`B`),
CONSTRAINT `_PostToUser_ibfk_1` FOREIGN KEY (`A`) REFERENCES `Post` (`id`) ON DELETE CASCADE,
CONSTRAINT `_PostToUser_ibfk_2` FOREIGN KEY (`B`) REFERENCES `User` (`id`) ON DELETE CASCADE
);
The relationship between User and Post right now is managed via the _PostToUser JOIN table.
However, I want to get rid of this extra JOIN table and simply have a foreign key reference from Post to User, so I ran this query to create the foreign key:
ALTER TABLE `Post` ADD COLUMN `authorId` char(25);
ALTER TABLE `Post` ADD FOREIGN KEY (`authorId`) REFERENCES `User` (`id`);
Now, I'm wondering what SQL query I need to run in order to migrate the data from the JOIN table to the new authorId column? If I understand correctly, I need a query that reads all the rows from the _PostToUser relation table and for each row:
Finds the respective Post record by looking up the value from column A
Inserts the value from column B as the value for authorId into that Post record
Note that I am aware that this changes the relationship from m-n and restricts it to 1-n: One post can at most have one author. One author/user can write many posts.
I'm basically looking for the equivalent of this PostgreSQL statement:
UPDATE "Post" post
SET "authorId" = post_to_user."B"
FROM "_PostToUser" post_to_user
WHERE post_to_user."A" = post."id";
Ensure that _PostToUser.A values are unique (no duplicated values). If exists - edit your data (remove excess records, for example).
Execute
UPDATE Post, _PostToUser
SET Post.authorId = _PostToUser.B
WHERE Post.id = _PostToUser.A
Ensure that there is no NULLs in Post.authorId

Why can't I drop a foreign key?

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

MySql - Product Variants Table (Wide Table) - Unique with NULLs

I have a products table, and a product_variants table (one-to-many).
The product_variants table has the following structure:
CREATE TABLE product_variants (
id int(11) NOT NULL AUTO_INCREMENT,
id_product int(11) NOT NULL,
id_colourSet int(11) DEFAULT NULL,
id_size int(11) DEFAULT NULL,
PRIMARY KEY (id),
UNIQUE KEY UNIQUE (id_product,id_colourSet,id_size),
KEY idx_prod (id_product),
KEY idx_colourSet (id_colourSet),
KEY idx_size (id_size),
CONSTRAINT fk_df_product_variants_id_colurSet FOREIGN KEY (id_colourSet) REFERENCES df_colour_sets (id_colourSet) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT fk_df_product_variants_id_product FOREIGN KEY (id_product) REFERENCES df_products (id) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT fk_df_product_variants_id_size FOREIGN KEY (id_size) REFERENCES df_sizes (id) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB
The options are known at compile-time. Each option is foreign-keyed to a dedicated table, and the unique key is the combination of all options.
I then insert products with an "ON DUPLICATE KEY UPDATE ..." statement, and if a variant already exists the query will use an existing variant.
The problem is that certain products do not have a color, nor a size. In this case the unique constraint fails and I insert lots of almost-empty rows in the product_variants table.
In order to solve this problem I am creating a "NULL" value for each option (e.g. "NO_COLOR", "NO_SIZE") in the respective option tables, and using that as the default value for the option columns in the product_variants table.
Would this be the recommended solution? Is there a better way of structuring this data? I would really like to avoid an EAV design.
Thank you
Designating a magic value that means "missing value" is not the right solution in almost every case. That's what NULL is for.
It's also not clear how "NO_COLOR" is used for an integer. I guess it would map to the value 0, which is typically not used in an auto-increment column.
You can create another column to be a hash of the three unique key columns, defaulted to '' to avoid null problems. Then put a unique constraint on that hash.
CREATE TABLE product_variants (
id int(11) NOT NULL AUTO_INCREMENT,
id_product int(11) NOT NULL,
id_colourSet int(11) DEFAULT NULL,
id_size int(11) DEFAULT NULL,
option_hash binary(16) NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY (option_hash),
KEY idx_prod (id_product),
KEY idx_colourSet (id_colourSet),
KEY idx_size (id_size),
CONSTRAINT fk_df_product_variants_id_colurSet FOREIGN KEY (id_colourSet) REFERENCES df_colour_sets (id_colourSet) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT fk_df_product_variants_id_product FOREIGN KEY (id_product) REFERENCES df_products (id) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT fk_df_product_variants_id_size FOREIGN KEY (id_size) REFERENCES df_sizes (id) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB;
CREATE TRIGGER product_variants_ins BEFORE INSERT ON product_variants
FOR EACH ROW SET option_hash = UNHEX(MD5(CONCAT_WS('|',
COALESCE(id_product, ''),
COALESCE(id_colourSet, ''),
COALESCE(id_size, ''))));
CREATE TRIGGER product_variants_upd BEFORE UPDATE ON product_variants
FOR EACH ROW SET option_hash = UNHEX(MD5(CONCAT_WS('|',
COALESCE(id_product, ''),
COALESCE(id_colourSet, ''),
COALESCE(id_size, ''))));