I’m having problems with a MySQL TRIGGER.
I have an employees table with some basic information. Then I have a VIEW that we call our finance_system. The finance_system VIEW holds a lot of information from many sources. A few columns in the finance_system are related to an internal sales draw and return random values from other tables each time the finance_system VIEW is queried. Lastly, I have a table called EP1. Its job is to hold some of the data from the finance_system, particularly some of the columns with random values. This keeps them from UPDATING /Changing with every query. The EP1 table gets updated via a TRIGGER that fires AFTER AN UPDATE to certain columns within the employees table. The trigger works and the EP1 table gets updated, but it’s updating the entire table rather than the rows associated to the employee_id that was updated.
I read Stacks policy prior to posting and understand a reproducible example is necessary so I created a Fiddle, but I’ve obfuscated the data and only included a few columns. Hopefully it’s enough as I’ve exhausted Google trying to figure out why it’s not working.
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=942dbabba180df86b7ac9317bbcdd64b
Edit:
Simpler version: When Table1.status is updated, the trigger should update Table3.rand1 with the values from Table2.rand1 where the ID’s match. Each ID has two rows in Table2 and Table3. My current problem is that when the trigger fires it updates all the rows in Table3 and I want it to only update the rows associated to the ID that was update in Table1. A join won’t work in this scenario, as Table2 is actually a VIEW using rand() in my real data.
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=329e2dd3bf2fff39afc5388721c53ddc
Aimee
Check the trigger's UPDATE query: it is missing a WHERE clause, hence all rows of Table3 get updated instead of the ones matching the desired id.
Related
I have a VIEW (view1) that returns random values from another table (Table2) based on values inside Table1.
A trigger is configured to UPDATE a third table (Table3), when values inside Table1 change. The purpose of Table3 is to hold the random values so they don’t get updated all the time.
The problem I have is that each select statement inside the trigger causes the whole row to get new random values for each column being updated. If there are multiple updates than it’s multiple times the whole row is getting new random values. I have adequate hardware, but it’s still too slow. Is there a way to reduce it, so maybe it selects once for each row, regardless of how many columns are receiving the updates? Maybe holds the values somewhere temporarily and updates from that?
Here is sample fiddle. In my real data I have significantly more columns.
Fiddle Example:
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=4fd8bf89135d8babe8c19fc15a565d50
Currently I don’t have indexes on any columns. I’ve read mixed reviews re indexes and updates.
Lastly, while browsing Stack I found a few links to this: https://jan.kneschke.de/projects/mysql/order-by-rand/, but I’m not sure there is a way I can apply it.
I have a table tblResponses which records responses received for each project in my database. Multiple responses per project, each with a date.
Another table tblActivity stores each activity on a project. Multiple activities per project.
I want to update each record in the Activity table with the date of the MOST RECENT response received for that project. If I use a GROUP BY query on tblResponses to get the Max(ResponseDate) grouped by projectID, I cannot then use this in an update query on tblActivity, as it makes the query not updateable.
At the moment I am having to populate a temporary table from the output of the GROUP BY query, and then use this in the Update query to update tblActivity. Not ideal as leads to database bloat etc, poor performance etc.
Is there any way to do this WITHOUT populating a temporary table? I understand why a Group By query cannot be updateable itself, but don't see why it cannot be used to provide the Update To values for updating another table.
(And yes, I know it shouldn't be necessary to store the result physically in a separate table when it could be calculated, but for various lengthy reasons, that isn't an option here.)
Many thanks for any help!
Jim
I have created a table ("texts" table) for storing ocr text from scanned documents. The table now has 100,000 + records. It stores a separate record for each page in the document. I set up the table originally so it stored the documents' title and its location against each record, which was obviously bad design as the info was duplicated for many records. I have subsequently created a separate table which now only stores one record for each document ("documents" table). The original table still contains a record for each page in the document, but the only columns now are the ocr text and the id of the document record in the documents table.
The documents table has a column "total_pages". I am trying to update this value using the following query:
UPDATE documents SET total_pages=(SELECT Count(*) from texts where texts.docs_id=documents.id)
This just seems to take forever to execute and I have had to crash out of it on a couple of occasions. There are over 8000 records in the documents table.
I have tested the query by limiting it to just one document
UPDATE documents SET total_pages=(SELECT Count(*) from texts where texts.docs_id=documents.id and documents.id=1)
This works eventually with just one record, but it takes a very long time to execute. I am guessing that my full query needs a bit of optimization! Any help greatly appreciated.
This is your query:
UPDATE documents
SET total_pages = (SELECT Count(*)
from texts
where texts.docs_id = documents.id)
For performance, you want an index on texts(docs_id). That will probably fix your performance problem. In fact, it might make it unnecessary to store this value in the master table.
If you do decide to store the count, be sure that you keep the value up-to-date. That would typically require a trigger to handle inserts and dates (and perhaps updates, if doc_id changes).
I have two tables with some same fields like:
Table A: fname, lname, address, age, email, mobile, website, blog
Table B: fname, lname, address, age, email
Both these tables are used by different modules on my website. I want to sync the first five fields of both tables in such a way that whenever a new row is added or an existing row is modified in Table A, the Table B is updated automatically and vice versa.
For Example.
A user created a new record in Table A. Now the Table B should also be updated with this new information. and vice versa if a user creates a new record in Table B, the Table A should also be updated with this new information.
A user modified a record in Table A. Now the Table B should also be updated with this modified information. and vice versa if a user modifies a new record in Table B, the Table A should also be updated with this modified information.
How can I achieve this. I thought of using triggers but would it not create an inifinite loop resulting is server error!
Is any field among those 5 guaranteed to be unique? You could add a conditional to the trigger to check to see if that field exists before inserting the record in the table.
You might want to rethink the design also. Storing duplicate records in 2 places seems a little scaring. You're going to have to have triggers for updates, inserts, and deletes.
If u just need to update one table in case the other table gets updated, Instead of creating a table (as a part of some other table), create a View which is also like a table but virtual (not real).
but since u've asked for both sides update.
What I believe is that you should go back little back of this problem....and tell us why u need to update both the tables according to the other table,,,
Because you are just keeping duplicate data at two places that is of no need.
So, try to think whether it can be done without creating two tables, or something like create one table and one view for partial columns requirement.
It is not an answer to your problem, but I am trying to solve your problem in an optimized way which is good for everyone's health....
Hope you understood what i tried to tell. :)
I'm using mysql to update a field in a table when a condition is met...
Should I first do a SELECT to see if the condition is met or do I just try to use UPDATE every time, because if the condition is not met, nothing happens.
To be concrete, here is my SELECT:
SELECT * FROM forum_subscriptions
WHERE IDTopic=11111 AND IDUser=11111 and status=0
I am checking here if I am on forum topic 11111 and if if I (user ID 1) is subscribed to this topic and my status on the subscription is 0 (that means that he didn't yet get email about new post in topic)
So when this is met do:
UPDATE forum_subscriptions SET Status=1 where IDTopic=11111 AND IDUser=1
Now I am wondering, I always do a select here to query if a user is subscribed to this topic and he has a status that he visited that topic before so any new posts will not trigger new email notification. When he visits the page again, the update is triggered that resets the visit so any new posts will again send him email.
So select is made on every user if he is subscribed or not to test the subscription. Update is made only when necessary.
Is it better to just use the update? To try to update on every page, if he is not subscribed to the topic it will not update anything.
How fast is update that doesn't produce any valid data? How is it made internally, how does update find if there is any record, does it select and then update? If so it would be better to only update because I would achieve same thing without any slowdowns. If the update is more expensive than select I should try to check first and then update if necessary.
This example is a real life example, but the logic behing this update/select is really what I am interested because I do find this kind of a problem more often.
Thanx
UPDATE: Thanx both guys, but I do not see on your links if UPDATE is locking even without results or not. As you gave different answers I still don't know what to do.
The subscription table really doesn't need to be myisam, I could change it to InnoDB because I don't have a need to fulltext it. Is this a good solution, to only use update and change this small table to inno? Does mixing table types have any drawbacks?
You just do the update, with no previous select:
UPDATE forum_subscriptions SET Status=1 where IDTopic=11111 AND IDUser=1
If the conditions are not met, update will do nothing.
This update is very fast if you have an index on status and IDtopic and IDuser!
An empty update is just as fast as an empty select.
If you do the select first, you will just slow things down for no reason.
If you want to know how many rows where updated do a
SELECT ROW_COUNT() as rows_affected
After doing the update, this will tell you 0 if no rows where updated, or the number of rows updated (or inserted or deleted, if you used those statements).
This function is ultra fast because it just has to fetch one value from memory.
Workarounds for table locking issues
See here: http://dev.mysql.com/doc/refman/5.5/en/table-locking.html
A potential side affect of always calling the UPDATE is the locking that needs to be put to insure that no other connection modifies these rows.
If the table is MyISAM - a lock will be places on the he entire table during the search.
If the table is InnoDB, locks will be places on the indexes/gaps.
From the Docs:
A locking read, an UPDATE, or a DELETE
generally set record locks on every
index record that is scanned in the
processing of the SQL statement. It
does not matter whether there are
WHERE conditions in the statement that
would exclude the row