mySqlTrigger改变它存在的同一个表

时间:2013-07-09 13:50:08

标签: mysql

我有一张简单的表

CREATE  TABLE `accounting`.`Foo` (
  `ID` INT NOT NULL AUTO_INCREMENT ,
  `This` VARCHAR(45) NULL ,
  `That` VARCHAR(45) NULL ,
  `The_Other` VARCHAR(45) NULL ,
  `Times_altered` INT NULL ,
  PRIMARY KEY (`ID`) );

我希望有一个触发器,只需计算此记录被更改的次数。我的'DBA'告诉我,我不能用触发器改变我在Mysql中的表,因为它会导致'循环'。

我不是一个SQL人员:但有些东西告诉我我需要一个新的DBA。

这实际上是真的吗?

我可以简单地增加Times_altered INT NULL吗?

2 个答案:

答案 0 :(得分:1)

这样的事情:

CREATE  TABLE `accounting`.`Foo` (
  `ID` INT NOT NULL AUTO_INCREMENT ,
  `This` VARCHAR(45) NULL ,
  `That` VARCHAR(45) NULL ,
  `The_Other` VARCHAR(45) NULL ,
  `Times_altered` INT NULL ,
  PRIMARY KEY (`ID`) );

CREATE  TABLE `accounting`.`logs` (
  `ID` INT NOT NULL AUTO_INCREMENT ,
  `table` VARCHAR(45) NULL ,
  `update_count` int NULL ,  
  PRIMARY KEY (`ID`) );

CREATE TRIGGER `update_counter` UPDATE ON `Foo`
FOR EACH ROW BEGIN
   INSERT INTO logs SET update_count = update_count + 1 WHERE table = 'Foo';
END;

注意:上面的代码未经过测试。
http://dev.mysql.com/doc/refman/5.0/en/create-trigger.html

答案 1 :(得分:1)

触发器确实不是正确的选择。 MySQL中的触发器会受到更新语句影响的每一行的激活,这意味着如果更新10行,设计中的Times_altered列将更新10次。如果Times_altered中的相同值是在表的所有行中还是只在一个中?无论哪种方式都不是我认为最好的设计。

现在你可以在cetver的答案中找到第二张表。再次更新不是一种选择,因为它会产生错误的结果。这就是他插入的原因。然后你必须为每个表有多行,你必须查询最大值...但请注意,它可能仍然是错误的结果,这取决于你是否想要计算表的行是否被改变了一次一个陈述,或者影响了多少行。

我建议你要么这样做:

CREATE  TABLE `accounting`.`Foo` (
  `ID` INT NOT NULL AUTO_INCREMENT ,
  `This` VARCHAR(45) NULL ,
  `That` VARCHAR(45) NULL ,
  `The_Other` VARCHAR(45) NULL ,
  PRIMARY KEY (`ID`) );

CREATE  TABLE `accounting`.`logs` (
  `ID` INT NOT NULL AUTO_INCREMENT ,
  `table` VARCHAR(45) NULL ,
  `update_count` int NULL ,  
  PRIMARY KEY (`ID`) );

SET TRANSACTION ISOLATION LEVEL READ-COMMITED;
START TRANSACTION;
UPDATE Foo SET whatever = whatever;
UPDATE logs SET update_count = update_count + 1 WHERE table = 'Foo';
COMMIT;

为什么交易?这是为了使流程并发安全。

或者你使用存储过程(类似这样):

DELIMITER $$
CREATE PROCEDURE my_update (IN stmt varchar(1000), IN tablename varchar(100))
BEGIN
SET @sql = stmt;
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE stmt;
SET @sql = CONCAT('UPDATE logs SET update_count = update_count + 1 WHERE table = ', tablename, ';');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE stmt;
END $$
DELIMITER ;

然后你会使用这样的程序:

SET TRANSACTION ISOLATION LEVEL READ-COMMITED;
START TRANSACTION;
CALL my_update('UPDATE Foo SET whatever = whatever', 'Foo');
COMMIT;

或者您将start transaction放入程序中。