Mysql 如何分析,更新行时发生了什么

Mysql 如何分析,更新行时发生了什么,mysql,sql,audit-logging,Mysql,Sql,Audit Logging,我有一张这样的桌子: | id | address | name | oid | state | event_id | ctrl | ------------------------------------------------------------------- | 1 | test_addr_1 | test_1 | 25.345.17 | 1 | 0 | 15 | 我需要在更新行中的数据时获取事件id 我想这样做: | id |

我有一张这样的桌子:

| id |   address   |  name  |    oid    | state | event_id | ctrl |
-------------------------------------------------------------------
| 1  | test_addr_1 | test_1 | 25.345.17 |   1   |     0    |  15  |
我需要在更新行中的数据时获取事件id

我想这样做:

| id |   address   |  name  |    oid    | state | event_id | ctrl |
-------------------------------------------------------------------
| 1  | test_addr_1 | test_1 | 25.345.17 |   1   |     0    |  15  |
如果新名称不等于旧名称
event\u id=event\u id+1

如果新oid不等于旧oid
event\u id=event\u id+2

如果新状态不等于旧状态
event\u id=event\u id+4

如果新ctrl大于旧ctrl
event\u id=event\u id+8

# Params to procedure
PROCEDURE Write(IN pAddr VARCHAR(20), IN pName VARCHAR(20), IN pOid VARCHAR(20), IN pState TINYINT, IN pCtrl INT)

#procedure body
SET @ev = 0;
SELECT
CASE
    WHEN name != pName THEN SET @ev = @ev + 1
    WHEN oid != pOid THEN SET @ev = @ev + 2
    WHEN state != pState THEN SET @ev = @ev + 4
    WHEN ctrl > pCtrl THEN SET @ev = @ev + 8
END 
FROM table1 

UPDATE table1 SET ..... , event_id = @ev WHERE address = pAddr
我怎么做?还是最好不要借助SQL?

正如前面所建议的,可以在这里使用an来确保捕获所有来源的更改。不过,我建议作出两项改变:

1)审核表-使用其他表保存审核数据,因为这些表往往会增长,不建议在同一结构中混合操作和审核数据(即使在同一数据库中)

2)使用更友好的更改标志-从您的示例来看,您似乎是在整数值中设置位。虽然这提供了紧凑的数据(捕捉单个整数中的许多更改),但它需要更多复杂的操作来查看名称何时更改(例如)。审计表可以只包含位(1)列,如
nameChanged
oidChanged

CREATE TRIGGER table1Audit BEFORE UPDATE ON <table1>
FOR EACH ROW BEGIN
    SET @ev = 
        (CASE WHEN OLD.name != NEW.name THEN 1 ELSE 0 END) + 
        (CASE WHEN OLD.oid != NEW.oid THEN 2 ELSE 0 END) + 
        (CASE WHEN OLD.state != NEW.state THEN 4 ELSE 0 END) +  
        (CASE WHEN OLD.ctrl != NEW.ctrl THEN 8 ELSE 0 END)

    -- INSERT INTO someaudittable
    --'table1', @ev
END;
在更新之前创建触发器表1审核
每行开始
设置@ev=
(如果OLD.name!=NEW.name,则为1,否则为0结束)+
(当OLD.oid!=NEW.oid然后2 ELSE 0结束时的情况)+
(当OLD.state!=NEW.state然后4 ELSE 0结束时的情况)+
(如果OLD.ctrl!=NEW.ctrl,则为8,否则为0结束)
--插入到审计表中
--“表1”,@ev
结束;

已解决!感谢@Alexei。 我想知道为什么要将该行添加到历史记录表中

结果是:

CREATE TRIGGER SetReason BEFORE UPDATE ON <table1>
FOR EACH ROW BEGIN
    SET NEW.event_id = 
        (CASE WHEN OLD.name != NEW.name THEN 1 ELSE 0 END) + 
        (CASE WHEN OLD.oid != NEW.oid THEN 2 ELSE 0 END) + 
        (CASE WHEN OLD.state != NEW.state THEN 4 ELSE 0 END) +  
        (CASE WHEN OLD.ctrl != NEW.ctrl THEN 8 ELSE 0 END)    
END;
在更新之前创建触发器SetReason
每行开始
设置新的事件\u id=
(如果OLD.name!=NEW.name,则为1,否则为0结束)+
(当OLD.oid!=NEW.oid然后2 ELSE 0结束时的情况)+
(当OLD.state!=NEW.state然后4 ELSE 0结束时的情况)+
(如果OLD.ctrl!=NEW.ctrl,则为8,否则为0结束)
结束;

在我看来,更新后触发是一个更好的选择。顺便问一下,你能确定你的多个条件不会同时触发吗?谢谢!这对我很有帮助。我想知道,如果价值观不同,会发生什么。其思想是:如果ev==1(对象被重命名),如果ev==4(对象可能是工作的),如果ev==12(对象不是工作的)等等。更新事件id并将此行插入历史记录表。是否可以在同一个表中更新它?