12

特定のアイテムの料金を追跡するテーブルがあります。これらの料金は時間の経過とともに変化する可能性があるため、2 つの列 (startDate、endDate) を用意し、現在の一連の料金の endDate は常に遠い将来に設定します。入力された新しい行でいくつかの計算を行うために使用するトリガーが既にありますが、既にエントリがある項目を入力した場合、前のエントリの endDate を前日に設定したい新しいエントリの startDate と新しい endDate を、あらかじめ決められたはるか先の日付に変更します。最初に試したコードは次のとおりです。

CREATE
DEFINER=`root`@`%`
TRIGGER `im`.`splitBeforeIns`
BEFORE INSERT ON `im`.`split`
FOR EACH ROW
BEGIN
    SET NEW.tcPercent = (NEW.tcOfficeFee / NEW.globalFee) * 100 , NEW.proPercent = 100 - NEW.tcPercent, NEW.endDate = 20501231;
    UPDATE im.split set endDate = ADDDATE(NEW.startDate, -1) where procKey = NEW.procKey AND endDate = 20501231;
END$$

私が得るエラーは次のとおりです。

ERROR 1442: Can't update table 'split' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
4

4 に答える 4

16

これに対する答えは歓迎されないかもしれませんが、それはできません。

トリガーは、トリガーが呼び出された行と同じテーブルの別の行を更新できません。

これを行う一般的な方法は、ストアド プロシージャを作成して、ターゲット テーブルに挿入/更新し、他の行をすべてトランザクションで更新することです。

于 2012-06-28T15:19:25.790 に答える
8

(procKey、EndDate)にUNIQUE KEYが定義されている場合は、トリガーの2行目を削除できます。また、トリガーからハードコードされた日付を削除します。

CREATE
DEFINER=`root`@`%`
TRIGGER `im`.`splitBeforeIns`
BEFORE INSERT ON `im`.`split`
FOR EACH ROW
BEGIN
    SET NEW.tcPercent = (NEW.tcOfficeFee / NEW.globalFee) * 100 , NEW.proPercent = 100 - NEW.tcPercent;
END$$

そして、次のようにINSERT ON DUPLICATEKEYUPDATEを実行します。

INSERT INTO im.split ...
ON DUPLICATE KEY UPDATE
endDate = ADDDATE(startDate, -1);

次のようにim.splitでendDateを定義することもできます。

enddate DATE DEFAULT '2050-12-31'
于 2012-06-28T17:06:17.683 に答える
3

FEDERATEDストレージエンジンを使用して、ターゲットテーブルと同じフィールドで定義された「ラッパーテーブル」を作成することで、なんとか機能させることができました。私が定義したフェデレーション サーバーは、同じ mysql サーバー/それ自体を対象とするため、"localhost" になります。次に作成したトリガーは、ラッパー テーブルの行を変更しました。もちろん、再帰ループを避けるために、トリガーで何をするかを十分に確認する必要があります。また、パフォーマンスがあまり良くない可能性もあります。パフォーマンスはテストしていませんが、本番環境で何年も動作しています。

于 2013-11-19T12:34:23.960 に答える
1

MySQL ドキュメントから:

ストアド関数またはトリガー内では、関数またはトリガーを呼び出したステートメントによって (読み取りまたは書き込みのために) 既に使用されているテーブルを変更することは許可されていません。

やろうとしていることを別の方法で行う必要があります。

于 2012-06-28T15:19:33.823 に答える