我试图在数据库触发器中实现行的版本控制。我有2个表:
1.地址(ID,城市,街道,国家)
- address_versions(id,object_changes)
我想在addresses_versions表中创建一行,每次从地址表中更改一行。
我创建了以下触发器:
CREATE TRIGGER `addresses_after_create` AFTER INSERT ON `addresses` FOR EACH ROW
this_trigger:BEGIN
DECLARE object_changes_json JSON;
-- Prepare object_changes JSON for address_versions row creation
SET object_changes_json = JSON_OBJECT();
IF COALESCE(OLD.city, '') <> COALESCE(NEW.city, '') THEN
SET object_changes_json = JSON_SET(object_changes_json, '$.city', JSON_ARRAY(OLD.city, NEW.city));
END IF;
IF COALESCE(OLD.street, '') <> COALESCE(NEW.street, '') THEN
SET object_changes_json = JSON_SET(object_changes_json, '$.street', JSON_ARRAY(OLD.street, NEW.street));
END IF;
IF COALESCE(OLD.country, '') <> COALESCE(NEW.country, '') THEN
SET object_changes_json = JSON_SET(object_changes_json, '$.country', JSON_ARRAY(OLD.country, NEW.country));
END IF;
INSERT INTO address_versions (object_changes)
VALUES (object_changes_json);
字符串
因此,每次我更改地址表中的一行时,都会使用更改值的JSON创建address_versions行。
但是上面的解决方案的问题是,我每次向表中添加/删除列时都需要更新触发器。
有没有一种方法可以让它更动态?
我试图创建一个单独的表与列名和循环通过它,但我不能访问新/旧值动态
...
read_loop: LOOP
FETCH cursor_column_name INTO column_name_string;
IF done THEN
LEAVE read_loop;
END IF;
IF COALESCE(OLD.column_name_string, '') <> COALESCE(NEW.column_name_string, '') THEN
SET object_changes_json = JSON_SET(object_changes_json, '$.additional_info', JSON_ARRAY(OLD.column_name_string, NEW.column_name_string));
END IF;
END LOOP;
...
型
但它失败了:
=> ERROR 1054 (42S22): Unknown column 'column_name_string' in 'OLD'
型
是否有方法动态引用新/旧值?
1条答案
按热度按时间ia2d9nvy1#
不可以。游标返回的是数据值(字符串/数字/日期等),而不是标识符。如果不使用动态SQL,就不能将字符串用作标识符。
但是在触发器中,不允许使用动态SQL。
因此,您需要在添加或删除列的同时部署更新的触发器。
我承认这是很难做到没有停机时间。
另一种方法是在更新
addresses
表之后使用应用程序代码更新address_versions
。