web-dev-qa-db-ja.com

2列の結合されたコンテンツに重複を含めることはできません

これは難しい質問です。言葉にするのは難しいと思う。

列Aの内容が列Bに表示できない、またはその逆の2つの列があります。したがって、両方の列を組み合わせた内容は一意である必要があります。

つまり、列Aに既に存在する値をどちらか AまたはBで許可しないようにします。Bの場合も同様です(Bに重複がないor A)。

MySQLでこれをテーブルスキーマの変更のみで行う方法はありますか?

また、挿入を防ぐためにトリガーを使用したくありません。

MySQLバージョン8.0.18

2
prolink007

(トリガーを使用せずに)これを行うには、 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も持っていません(リストにこれを提案してください!)。

3
Vérace