から取得した INT を保持する変数が必要なトリガーがあるSELECT
ため、 を 2 回呼び出す代わりに 2 つの IF ステートメントで使用できますSELECT
。MySQLトリガーで変数をどのように宣言/使用しますか?
6 に答える
構文を使用して、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//
`CREATE TRIGGER `category_before_ins_tr` BEFORE INSERT ON `category`
FOR EACH ROW
BEGIN
**SET @tableId= (SELECT id FROM dummy LIMIT 1);**
END;`;
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$$
これを@ホームで試さないでください
必要なものを見つけるのに苦労したため、このソリューションを投稿しています。この投稿は私を十分に近づけました(そのおかげで+1) 。データがテストに一致する場合、挿入前に列データを再配置するための最終的な解決策は次のとおりです。
注:これは、私が継承したレガシープロジェクトからのものです。
- 一意のキーは
rridprefix
+の合成ですrrid
- 私が引き継ぐ前は、一意のキーの重複を防ぐ制約はありませんでした
- 2 つのテーブル (1 つは重複でいっぱい) をメイン テーブルに結合する必要がありましたが、これは現在、複合キーに制約があります (そのため、取得中のテーブルは汚れたテーブルからの重複を許可しないため、マージは失敗します)。
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
または、トリガーを呼び出す SQL に SELECT ステートメントを含めるだけで、トリガー行の列の 1 つとして渡されます。確実に 1 つの行 (したがって 1 つの値) のみを返すことが確実である限り。(そしてもちろん、トリガー内のロジックと相互作用する値を返してはなりませんが、それはどのような場合でも当てはまります。)