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

このレコードが変更された回数を単純にカウントするトリガーが必要です。私の「DBA」は、「ループ」が発生するため、トリガーを使用してMysqlにあるテーブルを変更できないと言っています。

私は SQL の専門家ではありませんが、何か新しい DBA が必要だと教えてくれました。

これは実際に本当ですか?

Times_alteredINT NULLを単純にインクリメントすることはでき ませんか?

4

2 に答える 2

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 に答える
1

トリガーは確かに正しい選択ではありません。MySQL のトリガーは、更新ステートメントの影響を受ける行ごとにアクティブ化されます。つまり、10 行を更新すると、デザインの Times_altered 列が 10 回更新されます。また、Times_altered の同じ値は、テーブルのすべての行にあるべきですか、それとも 1 つだけにあるべきですか? いずれにせよ、私の意見では最高のデザインではありません。

これで、cetver の回答のように 2 番目のテーブルを作成できます。繰り返しますが、更新はオプションではありません。誤った結果が生成されるためです。それが彼が挿入している理由です。次に、各テーブルに複数の行があり、最大値を照会する必要があります...ただし、テーブルの行が1回変更されたかどうかをカウントするかどうかによっては、それでも間違った結果になる可能性があることに注意してください1 つのステートメント、または影響を受けた行の数。

次のようにすることをお勧めします。

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 に答える