MySQL で一意の行を強制する
-
01-07-2019 - |
質問
にテーブルがあります MySQL
これには 3 つのフィールドがあり、そのうちの 2 つのフィールドの間で一意性を強制したいと考えています。こちらが表です DDL
:
CREATE TABLE `CLIENT_NAMES` (
`ID` int(11) NOT NULL auto_increment,
`CLIENT_NAME` varchar(500) NOT NULL,
`OWNER_ID` int(11) NOT NULL,
PRIMARY KEY (`ID`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
の ID
フィールドは代理キーです (このテーブルは ETL でロードされています)。の CLIENT_NAME
クライアントの名前を含むフィールドです OWNER_ID
ID はクライアントの所有者を示します。
一意のインデックスを使用してこれを強制できると思いました CLIENT_NAME
そして OWNER_ID
,
ALTER TABLE `DW`.`CLIENT_NAMES`
ADD UNIQUE INDEX enforce_unique_idx(`CLIENT_NAME`, `OWNER_ID`);
しかし、MySQL ではエラーが発生します。
テーブルを更新するための SQL コマンドの実行中にエラーが発生しました。指定されたキーが長すぎます。キーの最大長は 765 バイトです (エラー 1071)
他に何かアイデアがある人はいますか?
解決
MySQL は、765 バイトを超えるキーに一意性を強制することはできません (そして、どうやら 500 の UTF8 文字がこの制限を超える可能性があります)。
- CLIENT_NAME の長さは本当に 500 文字である必要がありますか?ちょっと過剰な気がします。
- hash(CLIENT_NAME) という新しい (短い) 列を追加します。代わりに、MySQL にそのハッシュの一意性を適用させます。
他のヒント
CONSTRAINTを見ましたか...個性的?
このテーブルには何か少し奇妙に思えます。実際にリファクタリングを考えてみます。ID と OWNER_ID は何を指しますか?またそれらの間にはどのような関係がありますか?
持つことに意味があるだろうか
CREATE TABLE `CLIENTS` (
`ID` int(11) NOT NULL auto_increment,
`CLIENT_NAME` varchar(500) NOT NULL,
# other client fields - address, phone, whatever
PRIMARY KEY (`ID`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `CLIENTS_OWNERS` (
`CLIENT_ID` int(11) NOT NULL,
`OWNER_ID` int(11) NOT NULL,
PRIMARY KEY (`CLIENT_ID`,`OWNER_ID`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
500 文字の文字列にそのような一意のキーを追加することは絶対に避けたいと思います。2 つの int に一意性を適用する方がはるかに効率的です。また、テーブル内の ID は、実際には ID を必要とするものを参照する必要があります。あなたのバージョンでは、 ID
フィールドはクライアント/所有者の関係だけを識別しているようですが、これは単なるマッピングであるため、実際には別の ID は必要ありません。
ここ. 。UTF8 文字セットの場合、MySQL は 1 文字あたり最大 3 バイトを使用することがあります。CLIENT_NAME は 3 x 500 = 1500 バイトです。短くする CLIENT_NAME
250まで。
後で: +1 は、名前のハッシュを作成し、それをキーとして使用します。