Duplicates data after joining trigger table with other tables - mysql

I want to fetch the BEFORE and AFTER data from TableProduct whenever there is an update. So I created a Before and After trigger queries in which the respected values from the trigger is stored in separate tables titled TableProduct_Before and TableProduct_After.
My challenge is I always get duplicates result whenever I try to INNER JOIN the three tables.
I have tried the DISTINCT and ORDER BY ID command but still the same challenge.
I made enquiry I was told I can't join trigger table values because it doesn't have a foreign key, I tried adding a foreign key but it didn't work saying foreign key already exists in TableProduct.
Please, I will appreciate any help thank you.

You are misunderstanding how triggers work. You can use either a before or after trigger.
The key is using new and old. Inside the body of the trigger, you have both the old and new values. In pseudocode, this looks like:
insert into archive (pk, old_value, new_value)
values (new.pk, old.value, new.value);

Both OLD and NEW data is available in both before and after trigger.
The difference is - BEFORE trigger fixes the attempt to update whereas AFTER fixes successful attempt result. I.e. BEFORE is executed anycase (but its changes may be rollbacked!), rather than AFTER.
See https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=dd19c611c7e2fbef88b2133dcaa61dfa
PS. Recent MySQL versions allows triggers chains - a lot of triggers on the same event fired one-by-one. So check that your saving trigger is the most last in this chain.

Related

What is proper way to set and compare variable inside an sql trigger

Am populating a table using a trigger after an insert event occurs on another table and that worked fine. However i then noticed that the trigger would still insert a new row for existing records. To fix this, I want to create the trigger again but this time it would only fire if a condition is met...but not having previously used triggers in the past am getting a syntax error and not able to identify what am doing wrong. Kindly have a look and help me fix this
CREATE TRIGGER `students_gen_insert`
AFTER INSERT ON `students` FOR EACH ROW
BEGIN
INSERT INTO records (student_id, subject_id)
SELECT new.student_id, subjects.subject_id
FROM subjects
WHERE category = new.class;
END;
Am currently using MySql 5.6.17 version.
It is generally not a good idea to SELECT from the table the trigger is on, and forbidden to UPDATE or INSERT (not that you are doing those). Assuming you are trying to get the values for the row just inserted, the first SET ... SELECT you have is needless; just use NEW.fieldname to get the fields of the inserted row.
The second SET ... SELECT and following condition are a bit confusing. If referential integrity is being maintained, I would think it would be impossible for the records table to refer to that particular student_id of the students table at the point the trigger is executed. Perhaps this was to avoid the duplicate inserts from the trigger's previous code? If so, it might help for you to post that so we can pinpoint the actual source of redundant inserts.

TRIGGER: Read NEW.values and OLD.values during "ON DUPLICATE KEY UPDATE"

I'm trying to write a mini-auditing system for individual tables in MySQL.
I had good luck working with basic INSERT/UPDATE/DELETE commands, however now a table I'm interested in auditing uses INSERT ... ON DUPLICATE KEY UPDATE.
By using a trigger ON BEFORE INSERT I can tell this event is occurring, however I can only get half the data I'm interested in. NEW.values are readily available, but I've no idea how to get the OLD.values that came before. I suppose I could do a query using the NEW.ID in existing table, but I'm not sure about performance and reliability.
I need the OLD.values because I'm storing both old and new values for each change event since I read somewhere that was a good idea for collapsing data etc...
Is there a way in MySQL 5.0 (or newer GA release) to reliably retrieve these values as though I were in an UPDATE trigger?
EDIT: Another wrinkle:
Looks like the NEW.values do not match the data after update. They match the INSERT statement not the ON DUPLICATE KEY UPDATE data that will actually go into the record.
It looks like the trigger event ON AFTER UPDATE also catches the ON DUPLICATE KEY UPDATE change. From here, I was able to get OLD/NEW values and perform the logging I needed to perform.

Get the table/primary-key of "cascade-deleted" rows

When I delete an item which triggers some foreign key cascade-deletes, is there a way to get back the table and primary key of the cascade-deleted rows in MySQL?
If there's no built in way to do this, should I just write a stored procedure to manually handle the cascades and then relay what it deleted?
The only way you can do this is by putting a trigger on the table you're cascading to and having it log what deletes were made. MySQL won't nicely push out which deletes happened to you. So you'll either have to select them first, or log them and select them later.

Sql Trigger to insert updated record into another table

i've been looking though different tutorials online,but i can't seem to find what i need.
I need to copy a record into a history table, every time it is updated.
Is there a way to do it with triggers without having to type out all of my data fields?
It would help if you posted a schema of your tables, and what exactly you want to be inserting into your history table, but for now I'll make some assumptions about the table you're updating, and what you want in your history table. As an aside, this trigger will not work for a copy-paste... as each subsequent update to a record will be unable to be inserted into your history table because of primary key violations.
CREATE TRIGGER trg_History AFTER UPDATE ON my_table
FOR EACH ROW INSERT INTO history_table VALUES (NEW.col1, NEW.col2, OLD.col1, OLD.col2 ... etc)
the NEW keyword refers to all the data being inserted/updated and OLD refers to, well, the old data before being overwritten.
Again, please be more specific with the information you need to be inserting, and what you've tried so far, as we can only help you with general syntax at this point in time.

MySQL is handling one SQL query at the time?

If you got 100 000 users, is MySQL executing one SQL query at the time?
Because in my PHP code I check if a certain row exists; if it doesn't it creates one. If it does, it just updates the row counter.
It crossed my mind that perhaps 100 users are checking if the row exists at the same time, and when it doesn't they all create one row each.
If MySQL is handling them sequentially I know that it won't be an issue, then one user will check if it exists, if not, create it. The other user will check if it exists, and since that's the case, it just updates the counter.
But if they all check if it exists at the same time and let's say it doesn't, then they all create one row and the whole table structure will fail.
Would be great if someone could shed some light on this topic.
Use a UNIQUE constraint or, if viable, make the primary key one of your data items and the SQL server will prevent duplicate rows from being created. You can even use the "ON DUPLICATE KEY UPDATE ..." syntax to specify the alternate operation if the row already exists.
From your comments, it sounds like you could use the user_id as your primary key, in which case, you'd be able to use something like this:
INSERT INTO usercounts (user_id,usercount)
VALUES (id-goes-here,1)
ON DUPLICATE KEY UPDATE usercount=usercount+1;
If you put the check and insert into a transaction then you can avoid this problem. This way, the check and create will be run as one one query and there shouldn't be any confusion