Reputation: 485
I have a mysql table which I need to split into two. Currently the table contains info about two loosely related entities.
For example the entities can be Employee of a firm and the firm's laptop he is tagged to.
The following table explains my example. I have a table employee
which has the following columns
employee_id,employee_name,employee_detail,join_date,laptop_id,laptop_type,laptop_tagged_date,laptop_details,laptop_make.
I need to split this table into 2 as shown below.
employee
table without the laptop columns
employee_id,employee_name,employee_detail,join_date.
A new laptop
table with employee_id as the key.
employee_id,laptop_id,laptop_type,laptop_tagged_date,laptop_details,laptop_make
The below statements are true for the current database design
employee
table is heavily used by the back end code. The back
end code is written in java and php.employee
table cannot be renamed.Implies I do not want to create 2
new tables.I want to retain the employee
table, but remove all the
laptop info from it.My question is
Upvotes: 2
Views: 2029
Reputation: 125925
Backup your existing database:
mysqldump my_db > backup.sql
Create a new, empty table laptop
(I'm not defining indexes or foreign key constraints in my example below, but you should do whatever is appropriate to your data structure):
CREATE TABLE laptop
SELECT employee_id,
laptop_id,
laptop_type,
laptop_tagged_date,
laptop_details,
laptop_make
FROM employee
WHERE FALSE;
Define triggers on the original table to forward each type of write operation (insert/update/delete) to the new table:
CREATE TRIGGER employee_insert AFTER INSERT ON employee FOR EACH ROW
INSERT INTO laptop VALUES (
NEW.employee_id,
NEW.laptop_id,
NEW.laptop_type,
NEW.laptop_tagged_date,
NEW.laptop_details,
NEW.laptop_make
);
CREATE TRIGGER employee_update AFTER UPDATE ON employee FOR EACH ROW
UPDATE laptop SET
employee_id = NEW.employee_id,
laptop_id = NEW.laptop_id,
laptop_type = NEW.laptop_type,
laptop_tagged_date = NEW.laptop_tagged_date,
laptop_details = NEW.laptop_details,
laptop_make = NEW.laptop_make
WHERE
employee_id <=> OLD.employee_id,
laptop_id <=> OLD.laptop_id,
laptop_type <=> OLD.laptop_type,
laptop_tagged_date <=> OLD.laptop_tagged_date,
laptop_details <=> OLD.laptop_details,
laptop_make <=> OLD.laptop_make;
CREATE TRIGGER employee_delete AFTER DELETE ON employee FOR EACH ROW
DELETE FROM laptop WHERE
employee_id <=> OLD.employee_id,
laptop_id <=> OLD.laptop_id,
laptop_type <=> OLD.laptop_type,
laptop_tagged_date <=> OLD.laptop_tagged_date,
laptop_details <=> OLD.laptop_details,
laptop_make <=> OLD.laptop_make;
Empty the new table (of anything the trigger has since inserted) and then, within the same transaction, use INSERT ... SELECT
to copy into it all incumbent data from the original table:
START TRANSACTION;
DELETE FROM laptop;
INSERT INTO laptop
SELECT employee_id,
laptop_id,
laptop_type,
laptop_tagged_date,
laptop_details,
laptop_make
FROM employee;
COMMIT;
Thoroughly search your codebase (including database-stored programs) for all operations that access the laptop columns in the original table. Note whether each operation:
only reads from those columns;
only writes to those columns; or
both reads from and writes to those columns (e.g. UPDATE employee SET laptop_tagged_date = laptop_tagged_date + INTERVAL 1 WEEK WHERE ...
).
Modify read operations to use the new table, splitting operations that both read and write into separate steps (e.g. UPDATE employee JOIN laptop ON ... SET employee.laptop_tagged_date = laptop.laptop_tagged_date + INTERVAL 1 WEEK WHERE ...
).
This change does not need to be effected atomically, as the original and new tables will be kept in sync by the triggers: some parts of your application can therefore read from the new table whilst others continue using the original table.
Do not proceed to the next step until you are satisfied that this step has been completed, as the next step will result in the tables becoming desynchronised. You could even use MySQL user permissions to prevent writing to the new table (except by the triggers) until you are satisfied that this step is complete.
Modify write operations to use the new table.
This change does not need to be effected atomically, as any writes to the original table will be forwarded to the new one by the triggers: some parts of your application can therefore write to the new table whilst others continue writing to the original table.
Drop the columns from the original table:
ALTER TABLE employee
DROP COLUMN laptop_id,
DROP COLUMN laptop_type,
DROP COLUMN laptop_tagged_date,
DROP COLUMN laptop_details,
DROP COLUMN laptop_make;
Upvotes: 2
Reputation: 6525
I can suggest you a possible way , when you are creating laptop
table use the following query type :-
create table laptop select employee_id,laptop_id,laptop_type,
laptop_tagged_date,laptop_details,laptop_make from
employee;
After creating the laptop
table in this above process, you can remove the specified columns from employee
table for getting your new employee table with relevant fields.
Delete column from employee
table.
alter table employee
drop column laptop_id,laptop_type,laptop_tagged_date,laptop_details,laptop_make;
Now the new employee
table has following fields :
employee_id,employee_name,employee_detail,join_date
Now the laptop
table has following fields :
mployee_id,laptop_id,laptop_type,
laptop_tagged_date,laptop_details,laptop_make
Hope it will help you.
Upvotes: 1
Reputation: 87
if you want to have 2 physical different tables you can adapt Sebastien M. answer as such :
create a laptop table with corresponding data to externalize them
CREATE TABLE laptop AS
SELECT DISTINCT employee_id,laptop_id,laptop_type,laptop_tagged_date,laptop_details,laptop_make
FROM employee
WHERE ...
provide a employee_laptop view to imitate the behaviour of employee and get backward compatibility
create view employee_laptop as
select employee_id, e.employee_name,e.employee_detail,e.join_date,
l.laptop_id,l.laptop_type,l.laptop_tagged_date,l.laptop_details,l.laptop_make
from employee e join laptop l using(employee_id);
then you have all the latitude to drop the unnecessary columns from the employee table
Upvotes: 1