Php 如何创建MySQL触发器来跟踪更改

Php 如何创建MySQL触发器来跟踪更改,php,mysql,triggers,Php,Mysql,Triggers,我有一个名为“products”的表,以下列是该表中的示例(尽管还有很多): 产品编号 价格 我们的成本 更新price/our_cost时,我想在products_history表中插入一行,其中包含以下内容: 正在更改产品标识 正在更改的字段 旧价值 新价值 进行更改的员工的员工id(在PHP中作为变量$login\u id提供给我) 这是我当前的触发器,虽然我希望它能正常工作(除了输入员工id),但我收到一个错误消息,说列计数与第1行的值不匹配 DELIMITER | CREAT

我有一个名为“products”的表,以下列是该表中的示例(尽管还有很多):

  • 产品编号
  • 价格
  • 我们的成本
更新price/our_cost时,我想在products_history表中插入一行,其中包含以下内容:

  • 正在更改产品标识
  • 正在更改的字段
  • 旧价值
  • 新价值
  • 进行更改的员工的员工id(在PHP中作为变量$login\u id提供给我)
这是我当前的触发器,虽然我希望它能正常工作(除了输入员工id),但我收到一个错误消息,说
列计数与第1行的值不匹配

DELIMITER |

CREATE TRIGGER after_update_products
    AFTER UPDATE ON products FOR EACH ROW
    BEGIN
        SET @History = '';

        IF NEW.price <> OLD.price THEN
            SET @History = CONCAT(@History, '(', OLD.products_id, ", price, ", OLD.price, ", ", NEW.price, "),");
        END IF;

        IF NEW.our_cost <> OLD.our_cost THEN
            SET @History = CONCAT(@History, '(', OLD.products_id, ", our_cost, ", OLD.our_cost, ", ", NEW.our_cost, "),");
        END IF;

        IF @History <> '' THEN
            SET @History = SUBSTRING(@History, 2, CHAR_LENGTH(@History) - 3);
            INSERT INTO products_history (products_id, field, old_value, new_value) VALUES (@History);
        END IF;
    END;
|

DELIMITER ;
分隔符|
更新产品后创建触发器
每行产品更新后
开始
设置@History='';
如果是新的价格,那么是旧的价格
设置@History=CONCAT(@History,“(”,OLD.products_id,“,price,”,OLD.price,“,”,NEW.price,“),”;
如果结束;
如果是新的,我们的成本是旧的,那么我们的成本是旧的
设置@History=CONCAT(@History,“(”,OLD.products\u id,“,our\u cost,”,OLD.our\u cost,“,”,NEW.our\u cost,”),”;
如果结束;
如果@History“”那么
设置@History=SUBSTRING(@History,2,字符长度(@History)-3);
插入产品历史(产品id、字段、旧值、新值)值(@history);
如果结束;
结束;
|
定界符;
我做错了什么

除此之外,我是否需要担心在我插入的内容周围加引号(当我这样做时,上面的错误仍然存在),并且转义会成为一个问题


另外,如何让PHP将$login\u id添加到更新的每一行?

为什么要创建一个额外的变量?你真的不需要它。你为什么不试试这个:

CREATE TRIGGER after_update_products
AFTER UPDATE ON products FOR EACH ROW
BEGIN
    IF NEW.price <> OLD.price THEN
        INSERT INTO products_history (products_id, field, old_value, new_value) VALUES (old.products_id,'price',old.price,new.price);
    END IF;

    IF NEW.our_cost <> OLD.our_cost THEN
        INSERT INTO products_history (products_id, field, old_value, new_value) VALUES (old.products_id,'our_cost',old.our_cost,new.our_cost);
    END IF;
END;
更新产品后创建触发器
每行产品更新后
开始
如果是新的价格,那么是旧的价格
将值(旧的.products\U id、'price',旧的.price,新的.price)插入到products\U历史记录(products\U id、字段、旧的\U值、新的\U值)中;
如果结束;
如果是新的,我们的成本是旧的,那么我们的成本是旧的
插入产品历史(产品id、字段、旧价值、新价值)值(旧.产品id、“我们的成本”、旧.我们的成本、新.我们的成本);
如果结束;
结束;

我不太清楚您的最后一个问题“另外,如何让PHP向更新的每一行添加$login\u id?”

为什么要创建一个额外的变量?你真的不需要它。你为什么不试试这个:

CREATE TRIGGER after_update_products
AFTER UPDATE ON products FOR EACH ROW
BEGIN
    IF NEW.price <> OLD.price THEN
        INSERT INTO products_history (products_id, field, old_value, new_value) VALUES (old.products_id,'price',old.price,new.price);
    END IF;

    IF NEW.our_cost <> OLD.our_cost THEN
        INSERT INTO products_history (products_id, field, old_value, new_value) VALUES (old.products_id,'our_cost',old.our_cost,new.our_cost);
    END IF;
END;
更新产品后创建触发器
每行产品更新后
开始
如果是新的价格,那么是旧的价格
将值(旧的.products\U id、'price',旧的.price,新的.price)插入到products\U历史记录(products\U id、字段、旧的\U值、新的\U值)中;
如果结束;
如果是新的,我们的成本是旧的,那么我们的成本是旧的
插入产品历史(产品id、字段、旧价值、新价值)值(旧.产品id、“我们的成本”、旧.我们的成本、新.我们的成本);
如果结束;
结束;
我不太清楚您的最后一个问题“另外,我如何让PHP向更新的每一行添加$login\u id?”

尝试从@History中删除“(”和“)”

INSERT INTO products_history (products_id, field, old_value, new_value) VALUES @History;
此外,您将无法让PHP脚本将登录id传递给触发器,因为这超出了PHP的影响。您可能无法使用触发器,可能必须在PHP脚本中构建该INSERT语句

尝试从@History中删除“(”和“)”

INSERT INTO products_history (products_id, field, old_value, new_value) VALUES @History;
此外,您将无法让PHP脚本将登录id传递给触发器,因为这超出了PHP的影响。您可能无法使用触发器,可能必须在PHP脚本中构建该INSERT语句

您可以简单地在产品列表中添加一个“employee_id”字段,然后,触发器应该如下所示:

CREATE TRIGGER after_update_products
AFTER UPDATE ON products FOR EACH ROW
BEGIN
    IF NEW.price <> OLD.price THEN
        INSERT INTO products_history (products_id, field, old_value, new_value, guy, date) VALUES (old.products_id,'price',old.price,new.price,new.employe_id,now());
    END IF;

    IF NEW.our_cost <> OLD.our_cost THEN
        INSERT INTO products_history (products_id, field, old_value, new_value, guy, date) VALUES (old.products_id,'our_cost',old.our_cost,new.our_cost,new.employe_id,now());
    END IF;
END;
更新产品后创建触发器
每行产品更新后
开始
如果是新的价格,那么是旧的价格
将值(old.products\u id、'price',old.price,new.employee\u id,now())插入到产品历史(products\u id,field,old\u value,new\u value,new\u value,guy,date)中;
如果结束;
如果是新的,我们的成本是旧的,那么我们的成本是旧的
插入产品历史(产品id、字段、旧值、新值、guy、日期)值(旧.产品id、“我们的成本”、旧.我们的成本、新.我们的成本、新.雇员id、now());
如果结束;
结束;
您可以简单地在产品列表中添加一个“employee\u id”字段,然后触发器应该如下所示:

CREATE TRIGGER after_update_products
AFTER UPDATE ON products FOR EACH ROW
BEGIN
    IF NEW.price <> OLD.price THEN
        INSERT INTO products_history (products_id, field, old_value, new_value, guy, date) VALUES (old.products_id,'price',old.price,new.price,new.employe_id,now());
    END IF;

    IF NEW.our_cost <> OLD.our_cost THEN
        INSERT INTO products_history (products_id, field, old_value, new_value, guy, date) VALUES (old.products_id,'our_cost',old.our_cost,new.our_cost,new.employe_id,now());
    END IF;
END;
更新产品后创建触发器
每行产品更新后
开始
如果是新的价格,那么是旧的价格
将值(old.products\u id、'price',old.price,new.employee\u id,now())插入到产品历史(products\u id,field,old\u value,new\u value,new\u value,guy,date)中;
如果结束;
如果是新的,我们的成本是旧的,那么我们的成本是旧的
插入产品历史(产品id、字段、旧值、新值、guy、日期)值(旧.产品id、“我们的成本”、旧.我们的成本、新.我们的成本、新.雇员id、now());
如果结束;
结束;

我已经尝试过了,并相应地调整了我的子字符串,但是我得到了以下错误:
您的SQL语法有错误;查看与您的MySQL服务器版本对应的手册,了解在'@History'附近使用的正确语法;如果结束;END'
我已经尝试过了,并相应地调整了我的子字符串,但是我得到了以下错误:
您的SQL语法中有一个错误;查看与您的MySQL服务器版本对应的手册,了解在'@History'附近使用的正确语法;如果结束;结束“
,因为如果一次进行大量更改,一次查询应该会更快。至于$login\u id。在历史记录中添加更改时,有一列是employee\u id,我需要触发器在employee\u id字段中插入$login\u id。也许正如Brian所说,您需要从PHP处理所有更改。您可以创建一个函数或存储过程,只需从PHP和sen调用它