55

から取得した INT を保持する変数が必要なトリガーがあるSELECTため、 を 2 回呼び出す代わりに 2 つの IF ステートメントで使用できますSELECT。MySQLトリガーで変数をどのように宣言/使用しますか?

4

6 に答える 6

56

構文を使用して、MySQLトリガーでローカル変数を宣言できDECLAREます。

次に例を示します。

DROP TABLE IF EXISTS foo;
CREATE TABLE FOO (
  i SERIAL PRIMARY KEY
);

DELIMITER //
DROP TRIGGER IF EXISTS bar //

CREATE TRIGGER bar AFTER INSERT ON foo
FOR EACH ROW BEGIN
  DECLARE x INT;
  SET x = NEW.i;
  SET @a = x; -- set user variable outside trigger
END//

DELIMITER ;

SET @a = 0;

SELECT @a; -- returns 0

INSERT INTO foo () VALUES ();

SELECT @a; -- returns 1, the value it got during the trigger

変数に値を割り当てるときは、クエリが行のセットや列のセットではなく、単一の値のみを返すようにする必要があります。たとえば、クエリが実際に単一の値を返す場合は問題ありませんが、複数の行を返すとすぐに「ERROR 1242: Subquery returns more than 1 row」が返されます。

LIMITまたはを使用MAX()して、ローカル変数が単一の値に設定されていることを確認できます。

CREATE TRIGGER bar AFTER INSERT ON foo
FOR EACH ROW BEGIN
  DECLARE x INT;
  SET x = (SELECT age FROM users WHERE name = 'Bill'); 
  -- ERROR 1242 if more than one row with 'Bill'
END//

CREATE TRIGGER bar AFTER INSERT ON foo
FOR EACH ROW BEGIN
  DECLARE x INT;
  SET x = (SELECT MAX(age) FROM users WHERE name = 'Bill');
  -- OK even when more than one row with 'Bill'
END//
于 2008-11-29T23:29:15.373 に答える
7
`CREATE TRIGGER `category_before_ins_tr` BEFORE INSERT ON `category`
  FOR EACH ROW
BEGIN
    **SET @tableId= (SELECT id FROM dummy LIMIT 1);**

END;`;
于 2008-11-27T21:58:54.337 に答える
7
CREATE TRIGGER clearcamcdr AFTER INSERT ON `asteriskcdrdb`.`cdr` 
FOR EACH ROW
BEGIN
  SET @INC = (SELECT sip_inc FROM trunks LIMIT 1);
  IF NEW.billsec >1 AND NEW.channel LIKE @INC 
    AND NEW.dstchannel NOT LIKE "" 
  THEN
    insert into `asteriskcdrdb`.`filtre` (id_appel,date_appel,source,destinataire,duree,sens,commentaire,suivi) 
      values (NEW.id,NEW.calldate,NEW.src,NEW.dstchannel,NEW.billsec,"entrant","",""); 
  END IF;
END$$

これを@ホームで試さないでください

于 2009-05-15T12:43:45.717 に答える
4

必要なものを見つけるのに苦労したため、このソリューションを投稿しています。この投稿は私を十分に近づけました(そのおかげで+1) 。データがテストに一致する場合、挿入前に列データを再配置するための最終的な解決策は次のとおりです。

注:これは、私が継承したレガシープロジェクトからのものです。

  1. 一意のキーはrridprefix+の合成ですrrid
  2. 私が引き継ぐ前は、一意のキーの重複を防ぐ制約はありませんでした
  3. 2 つのテーブル (1 つは重複でいっぱい) をメイン テーブルに結合する必要がありましたが、これは現在、複合キーに制約があります (そのため、取得中のテーブルは汚れたテーブルからの重複を許可しないため、マージは失敗します)。
  4. on duplicate key列が多すぎて変更される可能性があるため、理想的とは言えません

とにかく、これは重複キーをレガシー列に入れるトリガーであり、レガシーの不良データを保存できるようにします(テーブルの複合、一意キーをトリガーしません)

BEGIN
  -- prevent duplicate composite keys when merging in archive to main
  SET @EXIST_COMPOSITE_KEY = (SELECT count(*) FROM patientrecords where rridprefix = NEW.rridprefix and rrid = NEW.rrid);

  -- if the composite key to be introduced during merge exists, rearrange the data for insert
  IF @EXIST_COMPOSITE_KEY > 0
  THEN

    -- set the incoming column data this way (if composite key exists)

    -- the legacy duplicate rrid field will help us keep the bad data
    SET NEW.legacyduperrid = NEW.rrid;

    -- allow the following block to set the new rrid appropriately
    SET NEW.rrid = null;

  END IF;

  -- legacy code tried set the rrid (race condition), now the db does it
  SET NEW.rrid = (
    SELECT if(NEW.rrid is null and NEW.legacyduperrid is null, IFNULL(MAX(rrid), 0) + 1, NEW.rrid)
    FROM patientrecords
    WHERE rridprefix  = NEW.rridprefix
  );
END
于 2016-12-20T15:42:55.467 に答える
2

または、トリガーを呼び出す SQL に SELECT ステートメントを含めるだけで、トリガー行の列の 1 つとして渡されます。確実に 1 つの行 (したがって 1 つの値) のみを返すことが確実である限り。(そしてもちろん、トリガー内のロジックと相互作用する値を返してはなりませんが、それはどのような場合でも当てはまります。)

于 2008-11-27T23:29:27.103 に答える