これは難しい質問です。言葉にするのは難しいと思う。
列Aの内容が列Bに表示できない、またはその逆の2つの列があります。したがって、両方の列を組み合わせた内容は一意である必要があります。
つまり、列Aに既に存在する値をどちらか AまたはBで許可しないようにします。Bの場合も同様です(Bに重複がないor A)。
MySQLでこれをテーブルスキーマの変更のみで行う方法はありますか?
また、挿入を防ぐためにトリガーを使用したくありません。
MySQLバージョン8.0.18
(トリガーを使用せずに)これを行うには、 Firebird を使用するしかありません。質問(MySQL)には実際には答えませんが、探求する興味深い機能です-フィドルを参照してください ここ !
CREATE TABLE test
(
column_A INTEGER NOT NULL,
column_B INTEGER NOT NULL,
CONSTRAINT a_uq UNIQUE (column_A),
CONSTRAINT b_uq UNIQUE (column_B),
CONSTRAINT a_ne_b_ck CHECK (column_A != column_B),
CONSTRAINT a_ni_b_ck CHECK (column_A NOT IN (SELECT column_B FROM test)),
CONSTRAINT b_ni_a_ck CHECK (column_B NOT IN (SELECT column_A FROM test))
);
それはテーブル宣言をより複雑にします(con)が、トリガーを自分で維持する必要がないという大規模なproがあります。エラーメッセージから、Firebirdがトリガーをバックグラウンドで使用しているように見えます。サーバーよりもトリガーを維持するほうが私よりも優れています。
--
-- The next two INSERTs work (as one would expect)
--
INSERT INTO test VALUES (2, 4);
INSERT INTO test VALUES (3, 5);
次に、テストする(最初に標準機能):
--
-- This doesn't work - breaches UNIQUE constraint on column_A
-- Look at the quality of the error message!
--
INSERT INTO test VALUES (2, 7); -- 2 is a dup in column_A
エラーで失敗します:
violation of PRIMARY or UNIQUE KEY constraint "A_UQ" on
table "TEST" Problematic key value is ("COLUMN_A" = 2)
そのエラーメッセージの品質を確認してください。問題のある値を教えてください。
次に、(ここでも標準のCHECK
制約に関するもの)を試します。
--
-- This doesn't work - breaches the column_A != column_B CHECK. Easy, peasy!
-- All RDBMS do this - even MySQL now since version 8!
--
INSERT INTO test VALUES (4, 4);
エラーメッセージ:
Operation violates CHECK constraint A_NE_B_CK on view or
table TEST At trigger 'CHECK_1'
次に、CHECK
制約内でSQLをテストします!
--
-- This is where it gets interesting! Notice that it **_won't_** allow a value
-- that's in column_B be inserted into column_A! Pretty cool!
--
INSERT INTO test VALUES (5, 9);
エラーを与える:
Operation violates CHECK constraint A_NI_B_CK on view or table
TEST At trigger 'CHECK_3'
CHECK
制約内のSQLは逆方向にも機能します-フィドルを参照してください。それが言うところのエラーメッセージの部分に注意してください:table TEST At trigger 'CHECK_3'
-バックグラウンドで動作しているトリガー!
これは本当に強力なものです! Firebirdがそれほど普及していない/普及していないのはとても残念なことです。 F/LOSS データベースエコスフィアに2スポット!
信じられないことに、MySQLは最近、CHECK
制約を導入しました(他のすべての主要な-そしてそれほどメジャーではない-競合他社から少なくとも25年後にのみ)。しかし、今は追いつくために真剣な努力をしているようです!しかし、他の誰も(AFAIK)はCHECK
制約にSQLを持っておらず、強力なOracle、MS SQL Server、PostgreSQLも持っていません(リストにこれを提案してください!)。