MySQLの複数の列に一意の制約を指定するにはどうすればよいですか?


865

テーブルがあります:

table votes (
    id,
    user,
    email,
    address,
    primary key(id),
);

今、私は列を作りたいです ユーザー、電子メール、アドレスを(一緒に)一意にします

MySqlでこれを行うにはどうすればよいですか?

もちろん、この例は単なる例です。したがって、セマンティクスについては心配しないでください。

回答:


1436
ALTER TABLE `votes` ADD UNIQUE `unique_index`(`user`, `email`, `address`);

31
これは、INSERTステートメントのON DUPLICATE KEY句で適切に機能しますか?つまり、別の行のuser / email / address値と競合する行を挿入しようとした場合、INSERTは代わりにON DUPLICATE KEY句で指定されたアクションを実行しますか?
clizzin

6
そのように3つの組み合わせはユニークでしょうか?または、個々の3つの列はすべて一意ですか?
ゲイリーリンダール2011

95
MySQLワークベンチを使用している人のために:[インデックス]タブに移動し、タイプとしてUNIQUEを選択します。インデックスに名前を付け、「インデックス列」セクションで適切な列を確認します
Pakman

10
私のように、他の誰かが検索エンジンからこれを見つけた場合...そしてON DUPLICATE KEYが複合キーで機能するかどうかに関するClizzinの質問に答えるために-それは絶対に機能しますが、構文にいくつかの小さな調整が必要になります。stackoverflow.com/questions/9537710/…を
Joe

2
NULL値でも機能させる方法。NULL値を持つ2つの同じ行を挿入すると、これは機能しません...
Wasim A.

237

MySQLテーブルがあります。

CREATE TABLE `content_html` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `id_box_elements` int(11) DEFAULT NULL,
  `id_router` int(11) DEFAULT NULL,
  `content` mediumtext COLLATE utf8_czech_ci NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_box_elements` (`id_box_elements`,`id_router`)
);

一意キーは期待どおりに機能し、id_box_elementsとid_routerの複数のNULL行を許可します。

私はMySQL 5.1.42を実行しているので、おそらく上記の問題にいくつかの更新がありました。幸いなことにそれは機能し、うまくいけばそれはそのようにとどまるでしょう。


34
上記のjonstjohnの回答が既存のテーブルを更新する方法を示しているように、一意のインデックスで新しいテーブルを作成する方法を示しているので、この回答をマークアップしたいと思いました。それらは同じことをしますが、新しいテーブルを作成するか、既存のテーブルを更新するかによって異なります。:)
GazB

3
すべてのバッククォートとは何ですか、それらはいくつかの目的を果たしますか?
プク2013年

8
これは、これらの逆引用符を自動的に挿入する管理者(www.adminer.org)からの出力なので、列名として使用されるmysqlキーワードの衝突には問題がありません。
Frodik 2013年

50

MySQLはNULLを一意の値として扱い、少なくとも現在は複数列のインデックスでそれを回避するロジックがないため、行にNULL値がある場合、複数列の一意のインデックスは機能しません。はい、マルチカラムインデックスの多くの正当なアプリケーションを制限するため、動作は正気ではありません。バグ追跡...


11
明確化の2つのポイント:1)この動作はに当てはまりませんENGINE BDB、2)これは文書化された動作ですが、IMHOは驚くべき/不愉快である可能性があるため、十分に文書化されていません。議論については、MySQLバグ25544 bugs.mysql.com/bug.php?id=25544を参照してください。
ピルクロー

2
NULLに感謝し、私が抱えていた問題に対処しました...ハッシュチェックサムで行くと思います
Daniel Doezema

7
これは答えではありません。元の質問に対するコメントである必要があります。
限定的な贖い

公式ドキュメントによると:MySQL 5.1以降、BDBはサポートされなくなったことに注意してください。
ジョージD.

2
非常に良い情報ですが、答えはありません。質問に周辺的にのみ関連しています。
Billynoah

23

これを試しましたか?

UNIQUE KEY `thekey` (`user`,`email`,`address`)

何エリックが私のためにうまく作品を言った:UNIQUE KEY thekey`( 、useremailaddress `。MYSQLバージョン5.5.24を使用しています。これを使用している場合は、PHPMYADMINでも設定できます。3.5.1バージョンのPMAを使用しています。
WQC

MySql 5.6で試してみました。最初の試みから動作します。エリック、ありがとう!
ローレンス

11

これはmysqlバージョン5.5.32で機能します

ALTER TABLE  `tablename` ADD UNIQUE (`column1` ,`column2`);

1
列名に一重引用符がなくても機能するようです。
Pratik Singhal 2016

7

MySql 5以降は次のように動作します(テストしたばかりです)。

  • null許容列を含む一意の制約を定義できます。一意の制約(A、B)を定義するとします。ここで、Aはnullにできませんが、Bは
  • そのような制約を評価するとき、(A、null)を必要なだけ(同じA値!)持つことができます。
  • (A、nullではない)ペアは1つだけ持つことができます

例:PRODUCT_NAME、PRODUCT_VERSION 'グラス'、null 'グラス'、null 'ワイン'、1

今度は( 'wine' 1)を再度挿入しようとすると、制約違反が報告されます。


説明してくれてありがとう 私はunique(A、B、C)を持っていて、なぜそれがnullと同じ非nullオプションの組み合わせを許可するのかを知りませんでした
AlexandruTopalăOct

6

phpMyAdminを使用して、複数列の一意のインデックスを追加できます。(バージョン4.0.4でテストしました)

移動した構造のターゲット表のためのページ。列の1つに一意のインデックスを追加します。構造ページの下部にある[ インデックス]リストを展開して、追加した一意のインデックスを表示します。編集アイコンをクリックすると、次のダイアログで、一意のインデックスに列を追加できます。


3

私はそれをこのようにします:

CREATE UNIQUE INDEX index_name ON TableName (Column1, Column2, Column3);

ユニークのための私の慣習index_nameTableName_Column1_Column2_Column3_uindexです。


2

一意のインデックスを追加するには、以下が必要です。

1)table_name
2)index_name
3)インデックスを追加する列

ALTER TABLE  `tablename` 
ADD UNIQUE index-name
(`column1` ,`column2`,`column3`,...,`columnN`);

あなたの場合、次のように一意のインデックスを作成できます。

ALTER TABLE `votes`ADD 
UNIQUE <votesuniqueindex>;(`user` ,`email`,`address`);

1

今後重複を避けたい場合。id2と言う別の列を作成します。

UPDATE tablename SET id2 = id;

2つの列に一意を追加します。

alter table tablename add unique index(columnname, id2);

1

mysqlでテーブルを作成している場合は、以下を使用します。

create table package_template_mapping (
mapping_id  int(10) not null auto_increment  ,
template_id int(10) NOT NULL ,
package_id  int(10) NOT NULL ,
remark      varchar(100),
primary key (mapping_id) ,
UNIQUE KEY template_fun_id (template_id , package_id)
);

0

最初に既存の重複を取り除きます

delete a from votes as a, votes as b where a.id < b.id 
and a.user <=> b.user and a.email <=> b.email 
and a.address <=> b.address;

次に、一意の制約を追加します

ALTER TABLE votes ADD UNIQUE unique_index(user, email, address);

制約を確認します

SHOW CREATE TABLE votes;

ユーザー、電子メール、アドレスのいずれかにnull値が含まれている場合、それらは一意と見なされることに注意してください。


0

PostgreSQLの場合...インデックスでは機能しませんでした。それは私にエラーを与えたので、私はこれをしました:

alter table table_name
add unique(column_name_1,column_name_2);

PostgreSQLは一意のインデックスに独自の名前を付けました。変更する必要がある場合は、テーブルのオプションでインデックスの名前を変更できると思います...

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.