How to copy a table (MySQL) and automatically update the new one? - mysql

I want to create a small copy of a bigger table and link both of them.
Every time I make an update in the bigger one, I want that the small one updates too.
For example, I have this data:
Big table:
id | name | price
1 | a | 10
2 | b | 12
Small table:
id | name
1 | a
2 | b
---- UPDATING THE BIGGER ONE ---
Big table:
id | name | price
1 | y | 10
2 | b | 12
3 | c | 13
Small table should become AUTOMATICALLY (after I update the bigger one):
id | name
1 | y
2 | b
3 | c
Do you know how to do it?

To do exactly what you're asking you could use triggers. Triggers are SQL that execute automatically when certain events happen. To mirror the data you would need to create UPDATE, INSERT, and DELETE triggers. (I don't have access to a MySQL instance at the moment to test, so there could be typos)
CREATE TRIGGER big_to_small_insert
AFTER INSERT ON big
FOR EACH ROW
INSERT INTO small (id, name) VALUES (NEW.id, NEW.name)
CREATE TRIGGER big_to_small_update
AFTER UPDATE ON big
FOR EACH ROW
UPDATE small SET name = NEW.name WHERE id = NEW.id
CREATE TRIGGER big_to_small_delete
AFTER DELETE ON big
FOR EACH ROW
DELETE FROM small WHERE id = OLD.id
However, a View is probably a better option if the "small" table is truly just the big table with a subset of data. A View won't store a copy of the data, so if you update the table (big) it will be reflected in the view (small), but the opposite is also true. If you do an INSERT, UPDATE, or DELETE on the view (small) it will actually happen in the table (big).
CREATE VIEW small AS
SELECT id, name FROM big

Related

mysql trigger one to many relation

So i have 3 tables Production, Stop_Prodcution and triggered_table.
production has a one to many realation with Stop_prodcution where a production can have a lot of stop prodcutions.
production table
-----------------------
id_prod | date
-----------------------
1 |20/03/2019
2 |18/04/2019
Stop_Production table
----------------------------
id_stop | name | id_prod
----------------------------
1 | Any reason | 1
2 | Lunch | 1
3 |damaged prod| 2
triggered_table
----------------------------
id|id_prod|date|id_stop|name
i've created 2 triggers:
after insert into production
for each row
insert into triggered_table
(id_prod,date) values (new.id_prod, curdate())
and the other one:
after update
set id_stop=new.id_stop,
name= new.name
where id_prod= new.id_prod
the problem is that a production record is able to have 2 or more stop_Production records so with the triggers that I have, it will update always the same record, but what I need is a new record with same information of production table and the information that differs from the new inserted row in stop_production, please tell me if I explained my self if not I'll try to be more clear.
This query will give you the results you want, without using a trigger:
SELECT
t1.id_stop,
t1.id_prod,
t1.`name`,
t2.date
FROM stop_production
LEFT JOIN production
ON (t1.id_prod = t2.id);
If you want to make a "table" out of this, you can create a view.
CREATE VIEW triggered_table AS (
SELECT
t1.id_stop,
t1.id_prod,
t1.`name`,
t2.date
FROM stop_production
LEFT JOIN production
ON (t1.id_prod = t2.id)
)
Then, if you want to SELECTfrom this "table", you can simply:
SELECT * FROM triggered_table;

How to update a column with specific data for each row? [duplicate]

I'm trying to update one MySQL table based on information from another.
My original table looks like:
id | value
------------
1 | hello
2 | fortune
3 | my
4 | old
5 | friend
And the tobeupdated table looks like:
uniqueid | id | value
---------------------
1 | | something
2 | | anything
3 | | old
4 | | friend
5 | | fortune
I want to update id in tobeupdated with the id from original based on value (strings stored in VARCHAR(32) field).
The updated table will hopefully look like:
uniqueid | id | value
---------------------
1 | | something
2 | | anything
3 | 4 | old
4 | 5 | friend
5 | 2 | fortune
I have a query that works, but it's very slow:
UPDATE tobeupdated, original
SET tobeupdated.id = original.id
WHERE tobeupdated.value = original.value
This maxes out my CPU and eventually leads to a timeout with only a fraction of the updates performed (there are several thousand values to match). I know matching by value will be slow, but this is the only data I have to match them together.
Is there a better way to update values like this? I could create a third table for the merged results, if that would be faster?
I tried MySQL - How can I update a table with values from another table?, but it didn't really help. Any ideas?
UPDATE tobeupdated
INNER JOIN original ON (tobeupdated.value = original.value)
SET tobeupdated.id = original.id
That should do it, and really its doing exactly what yours is. However, I prefer 'JOIN' syntax for joins rather than multiple 'WHERE' conditions, I think its easier to read
As for running slow, how large are the tables? You should have indexes on tobeupdated.value and original.value
EDIT:
we can also simplify the query
UPDATE tobeupdated
INNER JOIN original USING (value)
SET tobeupdated.id = original.id
USING is shorthand when both tables of a join have an identical named key such as id. ie an equi-join - http://en.wikipedia.org/wiki/Join_(SQL)#Equi-join
It depends what is a use of those tables, but you might consider putting trigger on original table on insert and update. When insert or update is done, update the second table based on only one item from the original table. It will be quicker.

mysql update multiplecolumns vs compare values in multiple rows

Okay, talking millions of rows here..
Structure of like
EXAMPLE 1
some_data_before this| x_counter_total | y_counter_total | x_counter_week | y_counter_week | x_counter_year | y_counter_year
--------------------------------------------------------------------------------------------------------------------------------------
some_data_here... | 42142142....... | `241242142..... | 23214124...... | .............. | .............. |` ..............
And every of X and Y events to increment these columns vs this
EXAMPLE 2
table A
some_data_before this| x_counter_total | y_counter_total |
----------------------------------------------------------
some_data_here...... | 42142142....... | `241242142..... |
table B
key_connected_with_table_A | x_event | y_event | occured_timestamp
-------------------------------------------------------------------
id 21...................... | true | false | current_timestamp
My need is this. I need number of X and Y events in some time, past day/week/month/year etc.
My question is that Is it better to update(increment) multiple columns describing the time period i need, like in EXAMPLE 1 or is it better to
on each Event add a Row like in EXAMPLE 2 and then count total VOTES with same ID WHERE occured_timestamp - current_timestamo < TIMESTAMP_OF_A_WEEK for example. Which one is more efficient? talking millions of records, and thousands of request in a minute.
NO, I would keep them in a single table since then I would need to fire only one UPDATE statement but if you separate them to 2 tables then either you will need to execute 2 update statement (or) create a AFTER UPDATE TRIGGER to insert into the other table (or) probably do a update join to update all the respective values ion both tables which to me looks more performance hit than having all the columns in single table.

How to merge rows with duplicate uniqe key on update in MySQL

I have following table structure:
+------------------+ +---------------------+
| Users | | Data |
+------------------+ +---------------------+
| id | uname_UK | | id |user_id_FK |data|
+-----|------------| +---------------------+
| 1 | foobar | | 1 | 1 | aa |
| 2 | bazqui +<-------+ 2 | 3 | bb |
| 3 | foobaz | | 3 | 2 | cc |
+------------------+ | 4 | 2 | dd |
+---------------------+
The problem now is, that during storing data in database there was typo. The user named foobaz should be named foobar. The uname column has a Unique constraint.
My question is how to easily fix this problem? When I update the username table, I get error - duplicate uniqe key, as expected. In the end I would like to have the foreign keys updated too.
My idea was do some trigger magic, but I was hoping there would be some more elegant solution. Another constraint here is, that the update is initiated through frontend, so I cannot use PHP.
Alternate way would be to drop the Unique constraint and make some cron job, to periodically update the database and remove the duplicate entries.
Thanks.
Why not just delete the record? Update all data to the user you want to keep and delete the obsolete user.
In Oracle you can do this using the merge into statement. I don't know if that is possible to do in one statement in MySQL, but you might as well execute a separate delete for it. You can make it trigger magic, but I doubt if it's a good decision to always autmagically merge the users. The new username might be a typo too.
So in a normal application, if this would happen so often, I would make a 'merge users' functionality that lets you do just this.
What you should do, is figure out what it means to your data that two users are actualy one. In this case, since there are two records in Data for user ID 2, it seems as if it's okay for users to have several records in Data and you can just
UPDATE data
SET user_id_FK = 1
WHERE user_id_FK = 3;
DELETE FROM users
WHERE id = 3;
In general, you need to figure this out at an application level.
What if there's a foo counter for each user? You should probably add the value from the user you'll be deleting to the value you're keeping.
What if a user has an address?
What if a user can only have one e-mail address and your duplicate user has a different one? Which do you keep?
This is not an easy question with a general answer.

Update one MySQL table with values from another

I'm trying to update one MySQL table based on information from another.
My original table looks like:
id | value
------------
1 | hello
2 | fortune
3 | my
4 | old
5 | friend
And the tobeupdated table looks like:
uniqueid | id | value
---------------------
1 | | something
2 | | anything
3 | | old
4 | | friend
5 | | fortune
I want to update id in tobeupdated with the id from original based on value (strings stored in VARCHAR(32) field).
The updated table will hopefully look like:
uniqueid | id | value
---------------------
1 | | something
2 | | anything
3 | 4 | old
4 | 5 | friend
5 | 2 | fortune
I have a query that works, but it's very slow:
UPDATE tobeupdated, original
SET tobeupdated.id = original.id
WHERE tobeupdated.value = original.value
This maxes out my CPU and eventually leads to a timeout with only a fraction of the updates performed (there are several thousand values to match). I know matching by value will be slow, but this is the only data I have to match them together.
Is there a better way to update values like this? I could create a third table for the merged results, if that would be faster?
I tried MySQL - How can I update a table with values from another table?, but it didn't really help. Any ideas?
UPDATE tobeupdated
INNER JOIN original ON (tobeupdated.value = original.value)
SET tobeupdated.id = original.id
That should do it, and really its doing exactly what yours is. However, I prefer 'JOIN' syntax for joins rather than multiple 'WHERE' conditions, I think its easier to read
As for running slow, how large are the tables? You should have indexes on tobeupdated.value and original.value
EDIT:
we can also simplify the query
UPDATE tobeupdated
INNER JOIN original USING (value)
SET tobeupdated.id = original.id
USING is shorthand when both tables of a join have an identical named key such as id. ie an equi-join - http://en.wikipedia.org/wiki/Join_(SQL)#Equi-join
It depends what is a use of those tables, but you might consider putting trigger on original table on insert and update. When insert or update is done, update the second table based on only one item from the original table. It will be quicker.