I've been using this MySQL trigger on a dedicated server, so every time a table is updated, it calculates a new sum and updates another table:
delimiter |
CREATE TRIGGER after_insert_rep_points AFTER INSERT ON users_reputation
FOR EACH ROW
BEGIN
DECLARE new_total INT(10);
SELECT SUM(rep_points) INTO new_total FROM users_reputation
WHERE user_id = NEW.user_id;
UPDATE users SET rep_total = new_total WHERE user_id = NEW.user_id;
END
|
delimiter ;
I now need to use this on a shared hosting environment, but unfortunately, due to security precautions, I cannot have SUPER USER privileges in a shared environment, which is required for triggers. I don't understand this. I think everybody should be able to use triggers.
I'm not that clued up on stored procedures, in-fact I'm useless, but I'm wondering if this query can be executed using one and if so, can anybody can give me any pointers?
The person who wrote the trigger obviously has very limited SQL skills - the whole body can be expressed as a simple query:
UPDATE users SET
rep_total = (SELECT SUM(rep_points)
FROM users_reputation
WHERE user_id = users.user_id)
WHERE user_id = ?; -- "?" is NEW.user_id inside the trigger. You must provide it
You don't need a stored procedure - just run this query.
Related
MySQL doesn't currently support updating rows in the same table the trigger is assigned to since the call could become recursive. Does anyone have suggestions on a good workaround/alternative? Right now my plan is to call a stored procedure that performs the logic I really wanted in a trigger, but I'd love to hear how others have gotten around this limitation.
Edit: A little more background as requested. I have a table that stores product attribute assignments. When a new parent product record is inserted, I'd like the trigger to perform a corresponding insert in the same table for each child record. This denormalization is necessary for performance. MySQL doesn't support this and throws:
Can't update table 'mytable' in stored function/trigger because it is already used by statement which invoked this stored function/trigger. A long discussion on the issue on the MySQL forums basically lead to: Use a stored proc, which is what I went with for now.
Thanks in advance!
You can actually up the rows in the same table as the trigger. The thread you linked to even has the solution.
For example:
TestTable ( id / lastmodified / random )
create trigger insert_lastmod
before insert on TestTable
for each row
set NEW.lastmodified = NOW();
insert into TestTable ( `random` ) values ( 'Random' );
select * from TestTable;
+----+---------------------+---------------------+
| id | lastmodified | random |
+----+---------------------+---------------------+
| 1 | 2010-12-22 14:15:23 | Random |
+----+---------------------+---------------------+
I suppose you could call the stored proc in your trigger. HOwever, if you want to update some fields in the same records that you are changing (such as an updatedby or lastupdated column) then you can do this in a beofre trigger according to the refernce manual. http://dev.mysql.com/doc/refman/5.0/en/trigger-syntax.html
This is a common operation for triggers and I find it difficult to believe it isn't supported.
If you want to update column that you don't read in trigger function, then as a workaround, you could put that column into separate table.
You can actually do that
The below is an example for same
DELIMITER $$
create trigger test2
before insert on ptrt
for each row
begin
if NEW.DType = "A" then
set NEW.PA = 500;
elseif NEW.DType = "B" then
set NEW.PA = 1000;
else
set NEW.PA = 0;
END IF;
END;$$
DELIMITER;
This worked for me :D
On Before / Update.
BEGIN
SET NEW.DateTimeUpdated = NOW();
END
Let's say that I have a series of tables in mysql, and some of them are dependent on other tables (so if I didn't want to force delete, i would have to delete them in order). Now let's say I had a little script to delete them in order...Now let's say I wanted to run that in mysql workbench, and better yet have a function that took in a parameter (like userId) and did the above... How would I do such a thing in Mysql workbench in a way that I could easily retrieve and run the code (like for example if I wanted to delete a user and all the other objects associated with the user.)
You can use a stored procedure
DELIMITER //
CREATE PROCEDURE delete_user(IN _user_id INT)
BEGIN
START TRANSACTION;
DELETE FROM user_data WHERE user_id = _user_id;
-- your other delete statements go here in a proper order
DELETE FROM users WHERE id = _user_id;
COMMIT;
END//
DELIMITER ;
Sample usage:
CALL delete_user(2); -- delete a user with id = 2
Here is a SQLFiddle demo
I had this trigger working fine on another sql server/database.. Now it does nothing, any prerequisites I need to setup or ideas why this isn't working.. SQL Server 2008
create trigger Autoupdate6 -- Creating Trigger
On NumericSamples
For Insert
As
Insert Into BM1OILT
Select SampleDateTime, SampleValue From NumericSamples
Where TagID = 8 and UpdateC = 0
UPDATE NumericSamples set UpdateC = 1 WHERE TagID = 8
go
Thanks,
Figured it out, the program that was inserting into the table was doing bulk inserts, there for by passing the triggers.. Went with a job instead of triggers. Thanks again Aaron Bertrand for trying to figure this out with me.
This will prevent the trigger from attempting to operate on the entire table:
CREATE TRIGGER dbo.Autoupdate6
ON dbo.NumericSamples
FOR INSERT
AS
BEGIN
INSERT INTO dbo.BM1OILT(...column names here please...)
SELECT SampleDateTime, SampleValue FROM inserted
WHERE TagID = 8 AND UpdateC = 0;
UPDATE n SET UpdateC = 1
FROM dbo.NumericSamples AS n
INNER JOIN inserted AS i
ON n.SampleDateTime = i.SampleDateTime
WHERE n.UpdateC = 0 AND n.TagID = 8;
END
GO
You might be able to collapse this to one statement using the OUTPUT clause, but there are so many limitations on composable DML, it's usually just wasted effort unless we already know that your environment is not subject to any of the restrictions.
MySQL doesn't currently support updating rows in the same table the trigger is assigned to since the call could become recursive. Does anyone have suggestions on a good workaround/alternative? Right now my plan is to call a stored procedure that performs the logic I really wanted in a trigger, but I'd love to hear how others have gotten around this limitation.
Edit: A little more background as requested. I have a table that stores product attribute assignments. When a new parent product record is inserted, I'd like the trigger to perform a corresponding insert in the same table for each child record. This denormalization is necessary for performance. MySQL doesn't support this and throws:
Can't update table 'mytable' in stored function/trigger because it is already used by statement which invoked this stored function/trigger. A long discussion on the issue on the MySQL forums basically lead to: Use a stored proc, which is what I went with for now.
Thanks in advance!
You can actually up the rows in the same table as the trigger. The thread you linked to even has the solution.
For example:
TestTable ( id / lastmodified / random )
create trigger insert_lastmod
before insert on TestTable
for each row
set NEW.lastmodified = NOW();
insert into TestTable ( `random` ) values ( 'Random' );
select * from TestTable;
+----+---------------------+---------------------+
| id | lastmodified | random |
+----+---------------------+---------------------+
| 1 | 2010-12-22 14:15:23 | Random |
+----+---------------------+---------------------+
I suppose you could call the stored proc in your trigger. HOwever, if you want to update some fields in the same records that you are changing (such as an updatedby or lastupdated column) then you can do this in a beofre trigger according to the refernce manual. http://dev.mysql.com/doc/refman/5.0/en/trigger-syntax.html
This is a common operation for triggers and I find it difficult to believe it isn't supported.
If you want to update column that you don't read in trigger function, then as a workaround, you could put that column into separate table.
You can actually do that
The below is an example for same
DELIMITER $$
create trigger test2
before insert on ptrt
for each row
begin
if NEW.DType = "A" then
set NEW.PA = 500;
elseif NEW.DType = "B" then
set NEW.PA = 1000;
else
set NEW.PA = 0;
END IF;
END;$$
DELIMITER;
This worked for me :D
On Before / Update.
BEGIN
SET NEW.DateTimeUpdated = NOW();
END
MySQL doesn't currently support updating rows in the same table the trigger is assigned to since the call could become recursive. Does anyone have suggestions on a good workaround/alternative? Right now my plan is to call a stored procedure that performs the logic I really wanted in a trigger, but I'd love to hear how others have gotten around this limitation.
Edit: A little more background as requested. I have a table that stores product attribute assignments. When a new parent product record is inserted, I'd like the trigger to perform a corresponding insert in the same table for each child record. This denormalization is necessary for performance. MySQL doesn't support this and throws:
Can't update table 'mytable' in stored function/trigger because it is already used by statement which invoked this stored function/trigger. A long discussion on the issue on the MySQL forums basically lead to: Use a stored proc, which is what I went with for now.
Thanks in advance!
You can actually up the rows in the same table as the trigger. The thread you linked to even has the solution.
For example:
TestTable ( id / lastmodified / random )
create trigger insert_lastmod
before insert on TestTable
for each row
set NEW.lastmodified = NOW();
insert into TestTable ( `random` ) values ( 'Random' );
select * from TestTable;
+----+---------------------+---------------------+
| id | lastmodified | random |
+----+---------------------+---------------------+
| 1 | 2010-12-22 14:15:23 | Random |
+----+---------------------+---------------------+
I suppose you could call the stored proc in your trigger. HOwever, if you want to update some fields in the same records that you are changing (such as an updatedby or lastupdated column) then you can do this in a beofre trigger according to the refernce manual. http://dev.mysql.com/doc/refman/5.0/en/trigger-syntax.html
This is a common operation for triggers and I find it difficult to believe it isn't supported.
If you want to update column that you don't read in trigger function, then as a workaround, you could put that column into separate table.
You can actually do that
The below is an example for same
DELIMITER $$
create trigger test2
before insert on ptrt
for each row
begin
if NEW.DType = "A" then
set NEW.PA = 500;
elseif NEW.DType = "B" then
set NEW.PA = 1000;
else
set NEW.PA = 0;
END IF;
END;$$
DELIMITER;
This worked for me :D
On Before / Update.
BEGIN
SET NEW.DateTimeUpdated = NOW();
END