How to put multiple updates in a trigger? - mysql

I hope you can help me here.
I am using MySQL + PhpMyAdmin and I have 2 tables in this problem.
Table 1: Accounts - id, account_name, website, etc. etc...
Table 2: Domains - id, domain_name, account_name
and I Inserted these queries into 2 triggers.
Before Update
update domains, accounts
set domains.account_name = NULL
where accounts.website != domains.domain_name
After Update
update domains, accounts
set domains.account_name = accounts.account_name
where domains.domain_name = main_accounts.website
With these, when I update something in the accounts table, it will automatically remove the account_name from domains table and put new account_name if a certain account is updated.
Images below will show example.
Tables not yet updated:
----------
Accounts Table
Domains Table
----------
----------
Updated View.
----------
----------
Accounts Table
Domains Table
So, on the second account table image, I have changed the domain and automatically, the domains table has been updated. I would want to make only 1 trigger that will contain those 2 update queries. I don't know if it's possible because after I complete this, I may also need to know how to update multiple different tables from 1 trigger. The reason why I ask is because I need to assign the account name for each sub-tables that are in use. Example, the main table is the accounts table and the sub tables that needs to be updated are:
domains.account_name
ip_address.account_name
phones.account_name
payments.account_name
So, I don't know if it's even possible to update those sub-tables under column "account_name" when the main table "accounts" is updated.
Thank you. I hope my question is clear. :D :D

You can group multiple statements into a trigger with BEGIN and END.
Example:
DELIMITER $$
CREATE TRIGGER my_trigger BEFORE INSERT ON accounts
FOR EACH ROW
BEGIN
-- Statement one
UPDATE domains
SET domains.account_name = accounts.account_name
WHERE domains.domain_name = main_accounts.website;
-- Statement two
UPDATE another_table
SET another_table.column_name = accounts.account_name
WHERE another_table.domain_name = accounts.some_column;
-- More UPDATE statements
END$$

Related

MySQL Trigger on update

I have a database with 2 tables. One tables contains data regarding references (job refs) the other contains votes. In order to get to the vote stage, you need 5 references. In another database, i must change a group_id once they have 5 refs.
I was trying to use something like below:
CREATE TRIGGER update_group AFTER UPDATE ON refs
FOR EACH ROW
BEGIN
IF (SELECT recruit_id from refs where count(refs) = 5) THEN
UPDATE users.members
SET group_id=10
WHERE member_id=recruit_id;
END;
Is something like this even feasible? if this doesn't work, my fallback is to use a bash script in a cron job that runs every 5 minutes, but a trigger just seems so much more efficient (and instantaneous)
You may use NEW. to refer respectively affected recruit_id after change, do a count and update the foreign table accordingly.
CREATE TRIGGER update_group AFTER UPDATE ON refs
FOR EACH ROW
BEGIN
SELECT #refs_no := count(*) from refs where recruit_id = NEW.recruit_id
IF (#refs_no = 5) THEN
UPDATE users.members
SET group_id=10
WHERE member_id=NEW.recruit_id;
END;

how to set limit on table containing record

I am using mySQL
Is there any way to set limit of table record/row? I have table X and want to set limit of total records/rows on table, for example 2rows. So no one can insert third record in table. This table should not allow to insert third record.
I do not want to use Triggers.
You can do it this the user grants, so the user cant write into this table and you can create a separate User for administration this table.
seee Manual : https://mariadb.com/kb/en/mariadb/grant/
If you dont want to use triggers, you 'll have to check the number of rows inside your application (if any).
Create an AFTER INSERT trigger on the table. - it's the only way to do it.
create trigger TableLimit
on TableName
after insert
as
declare #countTableRows int
select #countTableRows = Count(*)
from TableName
if #countTableRows > 2
begin
rollback
end
go

Identifying the edited columns in the database

At the beginning the application have an admins and employees and records.
The records table has many columns than can be changed by any employee. However, this change can not be submitted. When the admin approve for an edit the record will show up again in the system.
I was trying to identify the column name and the value, and send it to another table using triggers on UPDATE.
So when the employee edits any record, the record will be disabled in the system. Also the admin will be able to know which values has been changed.
Is this possible in databases ?
Records Table
-------------------------------------------------------------------
record_id record_name record_serial record_active
-------------------------------------------------------------------
1 something 5151 YES
When an update happens to the record_serial, such as from 5151 to 9844 I need to do this.
Records_changes
-------------------------------------------------------------------
change_id record_col record_old_val record_new_val
-------------------------------------------------------------------
1 record_serial 5151 9844
At the same time
-------------------------------------------------------------------
record_id record_name record_serial record_active
-------------------------------------------------------------------
1 something 9844 NO
I can do it using my application, but if there is anyway to do it using the database it would be much nicer.
I will use this to track the changes, and also create a history for the records old values.
I am using MySQL
You can do something like this
DELIMITER $$
CREATE TRIGGER tg_bu_records
BEFORE UPDATE ON records
FOR EACH ROW
BEGIN
IF NOT (OLD.record_serial <=> NEW.record_serial AND
OLD.record_name <=> NEW.record_name) THEN
SET NEW.record_active = 0;
END IF;
END$$
CREATE TRIGGER tg_au_records
AFTER UPDATE ON records
FOR EACH ROW
BEGIN
IF NOT (OLD.record_serial <=> NEW.record_serial) THEN
INSERT INTO records_changes (record_col, record_old_val, record_new_val)
VALUES ('record_serial', OLD.record_serial, NEW.record_serial);
END IF;
IF NOT (OLD.record_name <=> NEW.record_name) THEN
INSERT INTO records_changes (record_col, record_old_val, record_new_val)
VALUES ('record_name', OLD.record_name, NEW.record_name);
END IF;
END$$
DELIMITER ;
Note: The trick is to change record_active flag in BEFORE trigger because it's the only event when you can change values of a row being updated/inserted in a table on which you defined that trigger. Now in AFTER trigger we record the changes that have been made.
Here is SQLFiddle demo
A good database pattern for this, if I understand your problem correctly, is to use versioned rows. You add columns (or additional referenced tables) with meta data about when/who/what the edit was about. When a record is edited, a new row is inserted. Previous versions are never modified or deleted. Then it's up to your application logic to decide what to do with all of this.

MySQL Trigger - Update relation table with extra values

What I'm trying to achieve is, I want to automate the values of the table between the users and folders table. Since it's a many-to-many relationship I created the user_folders table. Currently the server (nodejs) gets the request with userid, clientfolderid and some an array of bookmarks (which are not important now). It checks if the user already has this folder, by selecting from the user_folders table and if it's not existing it inserts a new row into the folder table. Then it has to send another statement to insert into the user_folders table.
So I have to "manually" keep the users_folder table updated.I guess this is a common problem and wanted to know if there is a pattern or a proven solution? The odd thing is that MySQL automatically handles the deletion of rows with an AFTER DELETE trigger but there is no (at least that I know of) automation with an AFTER INSERT trigger.
As I already said an AFTER INSERT trigger could possibly solve it, but I think it's not possible to pass some extra parameters to the AFTER INSERT trigger. This would be the user_id and the folder_client_id in my case.
I was thinking of a solution that I could create another table called tmp_folder which would look like:
tmp_folder
-- id
-- title
-- changed
-- user_id
-- folder_client_id
Then create an AFTER INSERT trigger on this table which inserts into folders and user_folders and then removes the row from tmp_folder again. Would this be the right way or is there a better one?
I would basically do the same with the bookmarks and user_bookmarks table. The best thing would be if it's even possible to insert a folder then the owner into the user_folders table with user_id and folder_client_id and then multiple other users into user_folders with the user_id and an default folder_client_id of -1 or something which will be updated later.
Meanwhile thanks for reading and I hope you can help me :)
PS: Is there a name for the table between 2 other tables in an m-2-m relationship?
I don't see an easy way to do this via triggers, but a stored procedure may suit you:
DELIMITER //
CREATE PROCEDURE
add_user_folder(
IN u_user_id BIGINT UNSIGNED,
IN u_folder_client_id BIGINT UNSIGNED,
IN v_title VARCHAR(255)
)
BEGIN
DECLARE u_found INT UNSIGNED DEFAULT 0;
SELECT
1 INTO u_found
FROM
user_folders
WHERE
user_id = u_user_id AND
folder_client_id = u_folder_client_id;
IF IFNULL(u_found, 0) = 0 THEN
START TRANSACTION;
INSERT INTO
folders
SET
title = v_title,
changed = UNIX_TIMESTAMP();
INSERT INTO
user_folders
SET
user_id = u_user_id,
folder_id = LAST_INSERT_ID(),
folder_client_id = u_folder_client_id;
COMMIT;
END IF;
END;
//

Multiple MySQL queries (no PHP)

I am wondering if it is possible to perform a SQL query then update another table with the generated ID and continue through all of the rows?
I have this SQL query that works but what I need to do is after each row is added to cards to then update merged.cars_id with the last generated ID so they are linked. normally I would do this with PHP but ideally I would like to just do it with MySQL if possible.
MAIN QUERY
INSERT INTO cards (first_contact_date, card_type, property_id, user_id)
SELECT first_contact_date, 'P', property_id, user_id FROM merged
THEN I NEED WITH MATCHING ROWS (Roughly)
UPDATE merged SET merged.card_id = LAST_INSERT_ID (FROM ABOVE) into the matching record..
Is something like this possible and how do I do it?
I would recommend using MySQL triggers to do this
http://dev.mysql.com/doc/refman/5.0/en/create-trigger.html
A trigger is a function that will be executed AFTER or BEFORE the INSERT or DELETE or UPDATE is done over any record of your table.
In your case you need to do a AFTER INSERT on cards that just updates the merged table. Make sure its AFTER insert as you wont be able to access the new row's ID otherwise.
The code would look something like this, assuming the id field from the cards table its named "id"
delimiter |
CREATE TRIGGER updating_merged AFTER INSERT ON cards
FOR EACH ROW BEGIN
UPDATE merged SET card_id = NEW.id;
END;
|
delimiter ;
May I suggest Stored Procedures?
http://dev.mysql.com/doc/refman/5.0/en/create-procedure.html
--EDIT--
Ah yes, triggers. For this particular situation, Jimmy has the answer. I will leave this post for the sake of the link.
I would set up a trigger to do this. For mysql, read http://dev.mysql.com/doc/refman/5.0/en/triggers.html. This is what triggers are designed to handle.