3

レピュテーションの制約により、これは前の質問に対するこの回答のフォローアップ質問です。NULL値を処理しながら、各フィールドの変更をテストするより効率的な方法があるかどうかを知りたいです。

CREATE TABLE foo (
  a INT NULL DEFAULT NULL, 
  b INT NULL DEFAULT NULL,
  c INT NULL DEFAULT NULL
);

CREATE TABLE bar (
  a INT NULL DEFAULT NULL,
  b INT NULL DEFAULT NULL,
  c INT NULL DEFAULT NULL
);

INSERT INTO foo (a, b) VALUES (1, 2);

更新によって値が変更された場合にのみ、更新後にアクションが発生するトリガーが必要です。したがって、このUPDATEはINSERTになりません。

UPDATE foo SET a = 1 WHERE b = 2;

ただし、このUPDATEはINSERTになります。

UPDATE foo SET a = 2 WHERE b = 2;

私はそれを処理するためにこのトリガーを作成しましたが、IFステートメントを簡略化できることを望んでいます。

DELIMITER ///
CREATE TRIGGER t_after_update_foo
AFTER UPDATE ON foo
FOR EACH ROW 
  BEGIN
    IF
      ((OLD.a <> NEW.a OR OLD.a IS NULL OR NEW.a IS NULL) AND (NEW.a IS NOT NULL OR OLD.a IS NOT NULL))
      OR
      ((OLD.b <> NEW.b OR OLD.b IS NULL OR NEW.b IS NULL) AND (NEW.b IS NOT NULL OR OLD.b IS NOT NULL))
      OR
      ((OLD.c <> NEW.c OR OLD.c IS NULL OR NEW.c IS NULL) AND (NEW.c IS NOT NULL OR OLD.c IS NOT NULL))
    THEN
      INSERT INTO bar (a, b, c) VALUES (NEW.a, NEW.b, NEW.c);
    END IF;
  END;
///
DELIMITER ;

IFステートメントを簡略化できますか?または、より簡単な全体的な解決策はありますか?

4

2 に答える 2

5

を使用できますcoalesce()。これは、引数の最初の。であるを返しますnot null

if coalesce(old.a,'') <> coalesce(new.a,'') or
   coalesce(old.b,'') <> coalesce(new.b,'') or
   coalesce(old.c,'') <> coalesce(new.c,'')
   then
     insert ...;
   end if;

2番目の引数を選択するのは難しい場合があります。上記の例は、a、b、cが文字列であり、空の文字列値が値と同等である場合の一般的なケースで機能しnullます。

于 2012-12-18T19:23:20.707 に答える
5

これを行うには、 NULLセーフの等号演算子<=>を使用して比較し、を使用して結果を否定しNOTます。

それで、

((OLD.a <> NEW.a OR OLD.a IS NULL OR NEW.a IS NULL) AND (NEW.a IS NOT NULL OR OLD.a IS NOT NULL))

になります

!(OLD.a <=> NEW.a)

複数の列のいずれかが変更されたかどうかを確認するには、次のようにします。

!(OLD.a <=> NEW.a AND OLD.b <=> NEW.b)

比較する列が多数ある場合は、@ dlauzonの好意により、少し短い選択肢を使用できます。

!((OLD.a, OLD.b, OLD.c, ...) <=> (NEW.a, NEW.b, NEW.c, ...))
于 2014-06-04T15:41:16.827 に答える