1

私はこのテーブルを持っています

CREATE TABLE IF NOT EXISTS `links` (
  `link_id` int(20) NOT NULL AUTO_INCREMENT,
  `item1_id` int(20) NOT NULL,
  `item2_id` int(20) NOT NULL,
  PRIMARY KEY (`link_id`),
  UNIQUE KEY `item_id` (`item1_id`,`item2_id`)
) ENGINE=InnoDB;

ORに1 回しthe item_idか表示されないようにするには、どうすれば制約できますか?item1_iditem2_id

アイテムを他の1つのアイテムにのみリンクしたいので..

4

4 に答える 4

5

あるアイテムを他の1つのアイテムにのみリンクさせたい

これは、リンクテーブルが必要ないことを意味します。linkedItemIdアイテムテーブルに一意の制約がある列が必要なだけです。Item2がItem1にリンクされると(Item1IDはItem2行のlinkedItemIdにあります)、他の何もItem1にリンクできなくなります。

また、リンクテーブルには独自の代理キーは必要ありません

編集、MySQLは一意のインデックスで複数のNULLを許可することに注意してください(たとえば、フィルタリングされた一意のインデックスを使用してNULLを無視するSQL Serverとは異なります)

MySQL5.5からCREATEINDEX

すべてのエンジンで、UNIQUEインデックスは、NULLを含む可能性のある列に複数のNULL値を許可します

于 2012-02-01T12:58:33.613 に答える
1

INNODBがそのような制約(またはそのことについてはMyIsam)を強制できるとは思いません。私の提案は、挿入を処理するためのストアドプロシージャを作成することです。最初にカスタム制約のニーズを確認し、競合がない場合は通常どおり挿入します。

于 2012-02-01T12:58:36.077 に答える
1

を縮小しUNIQUE KEYて、のみにすることができitem1_idます。これは、テーブルが関係を定義し、1:1関係を定義しないことを意味します1:n。さらに、auto_increment主キーを削除できます。これらの「リンク」テーブルでは必要ありません。

CREATE TABLE IF NOT EXISTS links (
   item1_id int(20) NOT NULL,
   item2_id int(20) NOT NULL,
  PRIMARY KEY (item1_id),
  FOREIGN KEY (item1_id)                 --- I assume you have these 2
    REFERENCES item (item_id),           --- Foreign Keys, too
  FOREIGN KEY (item2_id)
    REFERENCES item (item_id)
) ENGINE=InnoDB;

これと@gbnの答えの違いは、これはNullを許可せず、リンクされていないアイテムを格納する必要がないことです。どちらのデザインもほぼ同じように機能しますが、Insert / Delete/Updateステートメントに若干の変更が加えられています。

ただし、どちらの設計でも、:、、、のようなカップルをリンクさせることが (1 -> 2)でき(2 -> 3)ます(3 -> 7)。それが必要な仕様を満たしている場合は、両方の設計で問題ありません。


ただし、リンクのいずれかの側で、リンクされた1つのカップルにのみアイテムを表示する場合は、実装が難しくなります。

links1つの方法は、テーブル内のすべての挿入が、両方(1, 2)を挿入して(2, 1)結合するか失敗する手順を介して行われるようにすることです(2行を処理する必要があるDelete / Updateステートメントの場合も同様です)。

他のより複雑な方法には、トリガー(または、MySQLでは使用できないインデックスビューなどのエキゾチックな構造)が含まれます。

正規化された設計が必要な場合は、このアプローチもあります(複雑ですがトリガーはありません)。

CREATE TABLE IF NOT EXISTS link_help (
   item1_id int(20) NOT NULL,
   item2_id int(20) NOT NULL,
  PRIMARY KEY (item1_id),
  FOREIGN KEY (item1_id) 
    REFERENCES item (item_id),  
  FOREIGN KEY (item2_id)
    REFERENCES item (item_id),
  UNIQUE KEY (item1_id, item2_id)          --- this will be needed below
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS links (
   item1_id int(20) NOT NULL,
   item2_id int(20) NOT NULL,
  PRIMARY KEY (item1_id),
  FOREIGN KEY (item1_id, item2_id) 
    REFERENCES link_help (item1_id, item2_id), 
  FOREIGN KEY (item2_id, item1_id)               --- notice the different 
    REFERENCES link_help (item1_id, item2_id)    --- order here
) ENGINE=InnoDB;

(1 -> 2)現在、テーブル(2 -> 3)(3 -> 7)行を追加することはできません 。links

于 2012-02-01T13:03:57.170 に答える
1

...そして、リンクに明示的な方向性があるかどうかという問題もあります-つまり、AB は BA とは異なりますか?

トリガーを使用して両方のケースに対処できると思います (これをテストする必要があります) ただし、MySQL の手続き型言語から明示的にエラーをスローできる方法は知りません。列がデフォルトなしで NOT NULL であることを指定したため、 NEW が書き込み可能であると仮定すると、....

CREATE TRIGGER ins_link BEFORE INSERT on links
FOR EACH ROW
BEGIN
  IF (NEW.item1_id = NEW.item2_id) THEN
      NEW.item2_id=NULL; /* subsequent INSERT will fail */
  END IF
  /* if you want AB=BA.... */
  IF (NEW.item1_id > NEW.item2_id) THEN
     @tempvar=NEW.item1_id;
     NEW.item1_id=NEW.item2_id;
     NEW.item2_id=@tempvar;
  END IF;
END;

(更新前のトリガーも必要になる場合がありますが、コードの残りの部分は同じです)。

于 2012-02-01T13:25:12.157 に答える