I cant get to execute the two statements in my trigger - mysql

I want both statements to be executed in my trigger. I can't get the following to work:
IF (flag = 'D') THEN
BEGIN
INSERT INTO logs (id, author_id, action_done, description, old_value, new_value, create_date)
VALUES (null, (SELECT id FROM gallery WHERE flag = 'D'), 'Delete', 'Gallery', (SELECT filename FROM gallery WHERE flag = 'D'), '', NOW());
DELETE FROM gallery WHERE flag = 'D';
END
END IF

I assume id field in logs table is a primary key and auto generated by system.
Try this:
IF (flag = 'D') THEN
BEGIN
INSERT INTO logs (author_id, action_done, description, old_value, new_value, create_date)
select id, 'Delete', 'Gallery', filename, '', NOW() from gallery where flag='D';
DELETE FROM gallery WHERE flag = 'D';
END
END IF

Your id should auto increment and thus should not be one of the values.

Presumably, your trigger is on the table gallery. If so, your trigger should be a "before" or "after" trigger and you can do:
IF (flag = 'D') THEN
BEGIN
INSERT INTO logs (author_id, action_done, description, old_value, new_value, create_date)
VALUES (old.id, 'Delete', 'Gallery', old.filename, '', NOW());
END;
END IF
There is no need to repeat the DELETE.

Related

How to write conditional query in MySQL?

I came from MSSQL and I'm trying to learn MySQL.
Documentation seem to not help me.
I don't want my query to start always with SELECT, I want my query to SELECT, INSERT or UPDATE depending on the condition. I can't seem to do it with MySQL. Here is my code:
IF COALESCE((SELECT 1 FROM gt_postmeta WHERE meta_value = '12345' LIMIT 1), 0) THEN
BEGIN
INSERT INTO gt_posts (
post_date,
post_content,
post_title,
post_name,
post_type )
VALUES (
'',
'0000493729150.jpg',
'SHAMROCK',
'',
'');
SET #parent_id = (SELECT id FROM gt_posts ORDER BY id DESC LIMIT 1);
INSERT INTO gt_postmeta(
post_id,
meta_key,
meta_value)
VALUES
(#parent_id, '_visibility', 'visible'),
(#parent_id, '_price', 'H72 SEMI-GLOSS DARK EARTH'),
(#parent_id, '_regular_price', 'H72 SEMI-GLOSS DARK EARTH'),
(#parent_id, '_sku', '12345');
INSERT INTO gt_warehouse(
warehouse_id,
stock,
product_sku)
VALUES(
'178',
'',
'12345');
END;
ELSE
BEGIN
IF COALESCE((SELECT 1 FROM gt_warehouse WHERE product_sku = '12345' AND warehouse_id = '178' LIMIT 1), 0) THEN
BEGIN
UPDATE
gt_warehouse SET stock = ''
WHERE product_sku = '12345'
AND warehouse_id = '178';
END;
ELSE
BEGIN
INSERT INTO gt_warehouse(
warehouse_id,
stock,
product_sku)
VALUES (
'',
'',
'',
'12345');
END;
END IF;
END;
END IF;
Follow: You must do the following things to perform this task in MYSQL
1- you have use STORED PROCEDURE in MYSQL to set query block as package exactly as in SQL SERVER but syntax is bit different
CREATE DEFINER=`root`#`localhost` PROCEDURE `sp_report`(
------
------
)
BEGIN
--Query block with condition
END;
2- You don't need COALESCE to check the existence of value, you can simply use EXISTS (LIMIT is also optional)
IF EXISTS(SELECT 1 FROM gt_postmeta WHERE meta_value = '12345') THEN
3- After this you may get minor issues like proper use of semicolon, BEGIN & END which you can resolve by yourself.
I think this should work:
SELECT id, login, ( IF(requires='privacy-weight',0,privacy-weight) ) AS privacy-weight, requires
FROM [mytable]
WHERE [mywhereclause]
For more information on how the IF function works in MySQL see the docs at http://dev.mysql.com/doc/refman/5.5/en/if.html

MySQL trigger regexp not working

I am trying to group users by their email address.
REGEXP is not working. Help
BEGIN
DECLARE group_id tinyint(4);
SET #user_email = ( SELECT email FROM `users` WHERE id = NEW.id );
IF (SELECT #user_email REGEXP '\.com$') THEN SET group_id = 17;
ELSE SET group_id = 18;
END IF;
INSERT INTO `user_usergroup_map` (`user_id`, `group_id`) VALUES (NEW.id, group_id);
END
--------- New -------------------
I did some more testing.
This worked...
BEGIN
INSERT INTO `user_usergroup_map` (`user_id`, `group_id`) VALUES( 3, 18 );
END
But this didn't work
BEGIN
INSERT INTO `user_usergroup_map` (`user_id`, `group_id`) VALUES(
NEW.id, 18);
END
Rather than try to figure out what is not working, let me suggest this simplification:
BEGIN
INSERT INTO `user_usergroup_map` (`user_id`, `group_id`)
SELECT NEW.id,
IF( email REGEXP '[.]com$', 17, 18 )
FROM users
WHERE id = NEW.id;
END
One difference: Your version will always insert a row; mine won't if id is missing from users.

MYSQL Event IF then run query

What would be the proper way to do this? tried many things and searched everywhere online
CREATE EVENT myevent
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 5 DAYS
DO
BEGIN
SELECT CASE WHEN funded IS NULL OR funded = ''
THEN INSERT INTO mytable1 (`id`, `to`) VALUES (NULL, 'admin')
ELSE
FROM mytable2 WHERE id='$id';
END
Try like this
DECLARE xFounded varchar(10);
SELECT funded into xFounded FROM mytable2 WHERE id='$id';
if xFounded is null or xFounded ='' then
INSERT INTO mytable1 (`id`, `to`) VALUES (NULL, 'admin');
ELSE
// Do Else Part Here
end if;
This is probably the shorest way.
insert into mytable1 (`id`, `to`) VALUES (NULL, 'admin') on duplicate key update id=LAST_INSERT_ID(id), to=to;
select LAST_INSERT_ID();

Mysql triggers - capture each column change

I am trying to create trigger, that capture changes in database after update.
Table my_table I am watching:
Table my_table_log where I am writing changes to log them
And here is trigger so far:
CREATE TRIGGER `log_update`
AFTER UPDATE ON `my_table`
FOR EACH ROW
BEGIN
INSERT INTO
`my_table_log`
(
`id`,
`action`,
`column_name`,
`value_before`,
`value_after`,
`who`,
`ts`
)
VALUES
(
NEW.id,
'u',
'name',
OLD.name,
NEW.name,
user(),
NOW()
);
END
Question: How to log each change of column ?
Problem: I am curently watching only if column name changed in my_table. And I have another trigger for column age. How to set trigger for each row and each column that was changed?
Thank you for your suggestions/code/inspirations
You might use ifs for every column you'd like to watch in your trigger:
create trigger `log_update`
after update on `my_table`
for each row
begin
if (old.name <> new.name) then
insert into `my_table_log`
(
`id`,
`action`,
`column_name`,
`value_before`,
`value_after`,
`who`,
`ts`
)
values
(
new.id,
'u',
'name',
old.name,
new.name,
user(),
now()
);
end if;
if (old.age <> new.age) then
insert into `my_table_log`
(
`id`,
`action`,
`column_name`,
`value_before`,
`value_after`,
`who`,
`ts`
)
values
(
new.id,
'u',
'age',
old.age,
old.age,
user(),
now()
);
end if;
end
But better make the insert a stored procedure to avoid redudancy:
create procedure `log_insert`
(
id int(11),
`action` char,
column_name varchar(255),
value_before varchar(255),
value_after varchar(255)
)
begin
insert into `my_table_log`
(
`id`,
`action`,
`column_name`,
`value_before`,
`value_after`,
`who`,
`ts`
)
values
(
id,
`action`,
column_name,
value_before,
value_after,
user(),
now()
);
end
And call it in your trigger:
create trigger `log_update`
after update on `my_table`
for each row
begin
if (old.name <> new.name) then
call log_insert
(
new.id,
'u',
'name',
old.name,
new.name
);
end if;
if (old.age <> new.age) then
call log_insert
(
new.id,
'u',
'age',
old.age,
new.age
);
end if;
end
You can re-use the stored procedure to log events in your insert and delete triggers.
Make shure to use a composite primary key in your my_table_log to allow updates over several columns. I'd use at least:
primary key(id,column_name,who,ts).
Or use dedicated single column primary key to avoid varchars in your primary key for better performance.
One alternative is to just log the new values together with user() and now():
create table my_table_log
( id ...
, name ...
, age ...
, action ...
, who ...
, ts ... )
To determine what was changed, compare with the previous row.
It is however rather expensive to determine what a row looked like at a certain point in time, you will have to find the last version before that point in time. Another model that makes this a lot easier is to keep track of begin_ts and end_ts for each row:
create table my_table_log
( id ...
, name ...
, age ...
, action ...
, who ...
, begin_ts ...
, end_ts ...)
The insert trigger adds a copy of the row with begin_ts = now() and end_ts = null. The update trigger updates end_ts = now() where end_ts is null and inserts a row like the insert trigger. The delete trigger updates end_ts and might add a copy together with who deleted the row. Determining what a row looked like at ts t is just a matter of where t between start_ts and end_ts

Get column name and values for MySQL trigger

I'm beginner with MySQL and I'm trying to create a log trigger that fills a log table like this:
DELIMITER $$
CREATE TRIGGER ai_user AFTER UPDATE ON user
FOR EACH ROW
BEGIN
INSERT INTO user_log (action,id,timestamp,column_name,old_value, new_value)
VALUES('update',NEW.id,NOW(),COLUMN.NAME,OLD.column_value, NEW.column_value);
END$$
DELIMITER ;
But I'm with problems to get the changed column name and it's old and new value.
Any help would be appreciated. Thanks.
You have to do this the painful way, one at a time:
if not (old.col1 = new.col1 or old.col1 is null and new.col1 is null)
INSERT INTO user_log(action, id, timestamp, column_name, old_value, new_value)
VALUES('update', NEW.id, NOW(), 'col1', OLD.col1, NEW.col1);
end if;
if not (old.col2 = new.col2 or old.col2 is null and new.col2 is null)
INSERT INTO user_log(action, id, timestamp, column_name, old_value, new_value)
VALUES('update', NEW.id, NOW(), 'col2', OLD.col2, NEW.col2);
end if;
. . .
Note that these do not have else clauses. You want to check for every value.
By the way, when you do updates this way, you need to be careful about types if the columns you are comparing have different types.