mysqlで不変のコラムを作成します
-
16-10-2019 - |
質問
一貫性の理由で、関係のある関係の列を変更できないようにしたいと思います。
バックストーリーは、「接続」関係に追加の値がある:n関係があるということです。誰もが関係パートナーのIDを変更できることを望んでいません。
私がこれまでに思いついたこと:
新しい値が古い値と同じかどうかをチェックするトリガーを作成します。しかし、条件が真実であると証明された場合、更新アクションを拒否する方法がわかりません。
これがこれまでの私のトリガーです:
CREATE TRIGGER deny_nton_change BEFORE UPDATE ON Schueler_in_Klasse
FOR EACH ROW BEGIN
IF NEW.Schueler_ID != OLD.Schueler_ID OR NEW.Klasse_ID != OLD.Klasse_ID THEN
END IF;
END;
解決
更新を中止するのではなく、それを無効にしますか?
...
FOR EACH ROW BEGIN
SET NEW.Schueler_ID = OLD.Schueler_ID;
SET NEW.Klasse_ID = OLD.Klasse_ID;
END
他のヒント
読みやすいエラーメッセージを中止および返すためのかなり素晴らしくてきれいな方法は、信号を使用することです。
Signal SqlState '45000' set message_text = 'schueler_idおよびklasse_idは変更されない場合があります!';
MySQLバージョンがこれをサポートしていることを確認してください。MySQL5.5で導入されました。以前のバージョンでは、存在しないフィールドを存在しないテーブルに挿入するなど、ハッキングが必要です。
GBNが言及しているように、新しい値を古い値で上書きすることも良い選択肢です。
私は実際にトリガーを中止するためのバックアリーアプローチを学びました. 。これは非常に粗雑ですが、信号処理がMySQLのストアドプロシージャ言語に実装されていないため機能します。せいぜいエミュレートできます。
第11章、本の254〜256ページ MySQLストアドプロシージャプログラミング サブヘディングの下 「トリガーによるデータの検証」 文字文字列をダミー整数に選択することを提案します(構文の観点からは正しいが、実行中に死ぬ[しゃれも意図しない]):
CREATE TRIGGER deny_nton_change BEFORE UPDATE ON Schueler_in_Klasse
FOR EACH ROW BEGIN
DECLARE dummy INT;
IF NEW.Schueler_ID != OLD.Schueler_ID OR NEW.Klasse_ID != OLD.Klasse_ID THEN
SELECT 'Cannot Carry Out This Trigger Any Further'
INTO dummy FROM table_you_know_does_not_exist WHERE 1=1 LIMIT 1;
END IF;
END;
INNODBを使用している場合、トリガーを使用せずにこれをきれいに行うことが実際に可能です。
たった1つの列で別のテーブルを作成します。その列には、問題の元のテーブルの不変の列を指す外部キー(したがって、このソリューションのINNODB要件)が必要です。
「更新制限」などの制限を設定します。
要約すれば:
CREATE TABLE original (
....
immutable_column ...
INDEX index1(immutable_column)
....
) ENGINE=INNODB;
CREATE TABLE restricter (
.....
col1,
INDEX index2(col1),
FOREIGN KEY (col1) REFERENCES original (immutable_colum) ON UPDATE RESTRICT ON DELETE CASCADE
) ENGINE=INNODB;
私が読んだすべての答えの組み合わせに基づいて、これは私のために働いたものです:
delimiter $$ -- You may need this or not (in my visual client I need it, directly in console I don't)
create trigger deny_nton_change before update on surveys
for each row begin
if new.Schueler_ID != old.Schueler_ID OR new.Klasse_ID != old.Klasse_ID then
signal sqlstate '45000' set message_text = 'My own Error: Field is immutable';
end if;
end$$
delimiter ; -- You may need this or not