sql trigger inserting row into two tables - mysql

I was looking for a way to create a trigger that would insert the same row into two tables with the same values.
For example, a new row is inserted into pushNotificationQueue as soon as that is inserted, I would like that same exact row to be inserted into messages.
I tried this
CREATE TRIGGER add_to_messages
after insert on mbb_pushNotificationQueue
FOR EACH ROW
insert into mbb_messages select * from mbb_pushNotificationQueue
the only problem with that is that it goes through and adds entries that have already been previously added.

You have to say with which rdbms you are working.
Anyway, you have to use a special table normally named inserted or similar.
This is for Sql Server:
INSERT INTO mbb_messages SELECT * FROM INSERTED
Others like Sybase use a REFERENCES clause to get to the newly inserted record:
create trigger TriggerName after insert on
TableName
referencing new as new_name
And for MySQL (which you are seem to use) you can refer to the newly inserted records by using the NEW table:
CREATE TRIGGER add_to_messages
after insert on mbb_pushNotificationQueue
FOR EACH ROW BEGIN
insert into mbb_messages select * from NEW;
END;

You need to use the column name with new keyword. Please find the trigger below:
DELIMITER $$
CREATE TRIGGER add_to_message
after insert on mbb_pushNotificationQueue
FOR EACH ROW BEGIN
insert into mbb_oushNotificationQueue(`col1`, `col2`) values(new.col1, new.col2);
END$$
DELIMITER ;

First of all, I say that using select * with an insert-select statement is really, really a bad idea. The reason is that you can never predict the order of the columns that are returned from a selection.
Secondly, assuming SQL Server, I would suggest using the following:
create trigger add_to_message
instead of insert on mbb_pushNotificationQueue
for each row
as
begin transaction
insert into mbb_oushNotificationQueue (col1, col2, col3)
select col1, col2, col3
from inserted
insert into mbb_messages (col1, col2, col3)
select col1, col2, col3
from inserted
if ##ERROR_LEVEL = 0
commit
else
rollback
Disclaimer:
This code has not been tested and may require some minor fixes, but is illustrating the idea very well.

I ended up using
CREATE TRIGGER add_to_messages
after insert on mbb_pushNotificationQueue
FOR EACH ROW
INSERT INTO mbb_messages SET messageID = NEW.messageID,
toUserID = NEW.toUserID,
fromUserID = NEW.fromUserID, message = NEW.message, dateReceived = NEW.dateReceived
Thanks to everyone who posted.

So only add the last record added.
insert into mbb_messages select blah from mbb_pushNotificationQueue where blah meets some criteria....
Having max(id) or something.

Related

Discuss the trigger for database table changes

hy,
This trigger will give me whole table record with all changes butt i want to get the last changed row share the code.
Create Or Replace Trigger TRG_check IN
Before insert or update
on temp_checkin
FOR each ROW
BEGIN
INSERT INTO temp_checkin_history
select * from temp_checkin
where temp_checkin.id = temp_checkin.id;
END;
thanks
Writing a query like INSERT INTO SELECT * without specifying the columns is a bad practice. Also, there is no need to select from the trigger owner table like you are doing. Instead, use :NEW keyword and specify all columns. You may write your trigger as
CREATE OR REPLACE TRIGGER trg_check BEFORE
INSERT OR UPDATE ON temp_checkin
FOR EACH ROW
BEGIN
INSERT INTO temp_checkin_history (
id,
col1,
col2,
col3
) --other columns
VALUES (
:new.id,
:new.col1,
:new.col2,
:new.col3
); -- other columns prefixed by :NEW
END;

Pass data from one table to another in mysql

I'm learning mysql and i try to pass data from one table to another.
In Details, i have table1 with columns id, firstname, lastname etc.
Then i have a table2 with columns id, firstname, lastname, bodyfat, bodyweight, matchid.
The thing that i want is to pass the data firstname and lastname from table1 to table2 and they should be matched on table1.id = table2.matchid. Also the procedure should happen every time that new records are inserted into the table1, so the specific values are also updated and displayed in table2.
Is there any way to achieve that?
Thanks, in advance!
Use an after insert trigger:
DELIMITER //
CREATE TRIGGER after_user_insert
AFTER INSERT
ON table1 FOR EACH ROW
BEGIN
INSERT INTO table2 (firstname, lastname, matchid)
VALUES
(NEW.firstname, NEW.lastname, NEW.id);
END; //
DELIMITER ;
This assumes that you only want to insert new records in table2 with the first and last name, which is all the available information in table1. You could include other columns in the insert, but you would have to specify how to do that.
Beyond this, if you needed to initially populate table2 from table1, you could do an INSERT INTO ... SELECT:
INSERT INTO table2 (firstname, lastname)
SELECT firstname, lastname
FROM table1
-- WHERE <conditions>
you can use a trigger on table 1. A trigger is a named database object that is associated with a table, and that activates when a particular event occurs for the table. Some uses for triggers are to perform checks of values to be inserted into a table or to perform calculations on values involved in an update.
You can set a trigger on insert event in table 1. Here is a link https://dev.mysql.com/doc/refman/5.7/en/triggers.html that shows examples of trigger in mysql. Hope this helps
You can Create Trigger on Table1 with the insert or update statement into the Table2 using AFTER keyword, so that whenever a data is inserted in the Table 1 the trigger will be invoked and does the respective action based on your trigger definition.
For more details about how to create and use a trigger for MySQL refer the below link.
https://dev.mysql.com/doc/refman/5.7/en/triggers.html

MariaDB sql trigger to update if key exists or insert if doesn't exist?

I'm new to SQL, but trying to build a simple trigger that will execute on each insertion. I want it to update some table values if the key already exists, or insert it with some new values if it doesn't exist.
Below is what I have attempted, but I would ideally want tester to be the thing that is being inserted. Something like NEW.reference_key?
CREATE TRIGGER key_access_monitor
BEFORE INSERT ON individual_key_log
FOR EACH ROW
BEGIN
IF EXISTS (SELECT reference_key FROM individual_key_log WHERE key = 'tester')
SELECT 'Found it!'
ELSE
SELECT 'Cannot find it!'
END IF
END
You want to insert a new row if a row with the same key does not already exist, and update the existing row if it does exist, is that correct?
You'd probably find it easier to use INSERT ... ON DUPLICATE KEY UPDATE, as follows:
INSERT INTO individual_key_log
(key, col1, col2, col3, ...)
VALUES
('tester', 'val1', 'val2', 'val3', ...)
ON DUPLICATE KEY UPDATE
SET col1 = 'val1', col2 = 'val2', col3 = 'val3', ...;
One of the problems with your trigger approach is that it is bad practice to attempt to query a table from within a row trigger on that same table, as it violates the ACID principle; many DBMSes do not permit it at all, raising a "Mutating Table" error. Updating a row from within an insert row trigger has the same problem magnified. A row trigger should never try to access its target table directly, instead accessing only the triggering row indirectly through OLD and NEW.
Hope that helps.

Use auto_increment value in INSERT

What actually I am trying to do is, insert a row with INSERT INTO table (col2, col3, <...>) VALUES (col1, $something, <...>).
col1 is an auto_increment id column, and basically I want to copy that value to col2 on INSERT statement, within one query. Is this possible?
If I have understood correct then in the same INSERT statement you are trying to insert the generated AUTO_INCREMENT ID to another column.
Well, that's not possible IMO; cause if you do so the AUTO_INCREMENT ID is still not generated.
One solution is to use a stored procedure and perform the INSERT+UPDATE together like below (a sample)
create procedure usp_dowork(parameter list ...)
as
begin
INSERT INTO table (col2, col3, <...>) VALUES (NULL, $something, <...>);
update table set col2 = LAST_INSERT_ID()
where col1 = LAST_INSERT_ID();
end
You should consider using a transaction block around the DML's to make sure both the operations happens successfully.

BEFORE INSERT TRIGGER on one table but insert should be done on another table

I have two tables say table1 and table2.
fields of table1 - id and count
fields of table2 - id and count
both tables have same fields. Now I want to create BEFORE INSERT TRIGGER on table1 which will check if count = 2 then insert into table2 otherwise in table1.
I created the trigger but when I fire this query ..example-
insert into table1 (id, count) values (1323, 2);
then one row is inserted into table2 (this I want) and same row is inserted into table1 also.
I want row should be inserted in table1 or table not in both tables.
what I do to achieve this ?
Try with this:
delimiter $$
CREATE TRIGGER myTrigger
BEFORE INSERT ON table1
FOR EACH ROW
BEGIN
IF NEW.count = 2 THEN
insert into table2 (id, count) values (New.id,New.Count);
ELSE
<<no action>>
END IF;
END$$
I'm not sure why you want this, so I suspect I might be giving advice on some sort of solution that should be fixed differently, but here we go.
As you can see in this question here it is not possible to neatly stop an insert. You could try and make an error so you'll not actually insert, but I think that is really painful.
What you can do is make a fake table dummytable and put your insert trigger there. Your row will always insert in the dummy table, but you either insert it in table1 or table2 according to your wishes. The meat of the trigger would look like
IF NEW.count = 2 THEN
INSERT INTO table2 (id, count) VALUES (New.id,New.Count);
ELSE
INSERT INTO table2 (id, count) VALUES (New.id,New.Count);
END IF;
You'll have to clean the dummytable now and then.