是否可以在触发器内循环遍历所有列名?
场景: 记录已修改的表的所有列。 如果某些值未更改,则不要记录这些值。
DROP TRIGGER IF EXISTS t_before_update_test;
DELIMITER $$
CREATE TRIGGER t_before_update_test
BEFORE UPDATE ON test
FOR EACH ROW
BEGIN
-- Loop here for all columns, not just col1
IF OLD.col1 <> NEW.col1 THEN
INSERT INTO change_logs(
log_on, user_id,
table_name, colum_name,
old_data, new_data
) VALUES (
UNIX_TIMESTAMP(NOW()), '0',
'test', 'col1',
OLD.col1, NEW.col1
);
END IF;
-- process looping all columns
-- col1, col2, ... should be dynamic per loop
END $$
这是工作副本示例,我现在需要在其中循环遍历 OLD 或 NEW 中可用的所有列。
最佳答案
我现在没有足够的时间来完成这个,但我认为使用 CONCAT()
来准备一个语句并将其结果用于条件可能会让你做你要。沿着这些线的东西:
DECLARE num_rows INT DEFAULT 0;
DECLARE cols CURSOR FOR SELECT column_name FROM information_schema.columns WHERE table_name = 'table_name' ORDER BY ordinal_position;
OPEN cols;
SELECT FOUND_ROWS() INTO num_rows;
SET @i = 1;
cols_loop: LOOP
IF @i > num_rows THEN
CLOSE cols;
LEAVE cols_loop;
END IF;
FETCH cols INTO col;
SET @do_stuff = 0;
SET @s = CONCAT('SELECT IF(NEW.', col, ' <> OLD.', col, ', 1, 0) INTO @do_stuff');
PREPARE stmt1 FROM @s;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
IF @do_stuff = 1 THEN
SET @s2 = CONCAT('INSERT INTO change_logs(log_on, user_id, table_name, colum_name, old_data, new_data )
VALUES (UNIX_TIMESTAMP(NOW()), ''0'', ''test'', ''', col,''', OLD.', col, ', NEW.', col, ');');
PREPARE stmt2 FROM @s2;
EXECUTE stmt2;
DEALLOCATE PREPARE stmt2;
END IF;
SET @i = @i + 1;
END LOOP cols_loop;
CLOSE cols;
关于mysql - 遍历 MySQL 触发器中的列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24228255/