-1

I have a simple table

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`) );

I wish to have a trigger simply count the under of times that this record is altered. My 'DBA' is telling me that I cannot alter the table I am in in Mysql with a trigger as it will cause a 'loop'.

I am not a SQL guy: but something tells me I need a new DBA.

Is this in fact true?

Cant I simply increment the Times_altered INT NULL ?

4

2 回答 2

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放入程序中。

于 2013-07-09T15:02:02.437 回答
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

于 2013-07-09T14:00:37.267 回答