web-dev-qa-db-ja.com

プライマリキーとしてVARCHARを使用できますか?

クーポン/割引を保存するためのテーブルがあり、coupon_code列を主キーとして使用します。これはVARCHARです。

私の理論的根拠は、各クーポンには固有のコードがあり、実行するコマンドはSELECT ... FROM ... WHERE coupon_code='..'

結合やインデックス作成は一切行いません。また、このテーブルには数百を超えるエントリが存在することはありません。

これは問題ないように思えますが、行方不明/考えていないものがあるかどうかはわかりません。

45
Mike Brady

もちろん、RDBMSでできるという意味で、できます。 shouldを行うかどうかの質問に対する答えは異なりますが、ほとんどの場合、データベースシステムの外部で意味を持つ値はnotを選択する必要があります主キーになります。

モデル化するシステム内で値が一意であることがわかっている場合は、一意のインデックスまたは一意の制約をテーブルに追加するのが適切です。ただし、主キーは通常、自動インクリメントされた番号やGUIDなどの「意味のない」値である必要があります。

この理由は簡単です。データ入力エラーと、変更不可能と思われるものへのまれな変更が発生します。主キーとして使用される値を修正するのははるかに困難になります。

98
dasblinkenlight

毛布「あなたはすべきではない」はひどいアドバイスです。これは、ユースケース、ワークロード、データエントロピー、ハードウェアなどに応じて、多くの状況で完全に合理的です。あなたがしてはいけないことは仮定をすることです。

MySQLのインデックス作成を制限するプレフィックスを指定できるため、残りをスキャンする前に結果を絞り込むのに役立ちます。ただし、これは、プレフィックスが「いっぱい」になり、一意性が低下するため、時間が経つにつれて有用性が低下する可能性があります。

それは非常に簡単です、例えば:

CREATE TABLE IF NOT EXISTS `foo` (
  `id` varchar(128),
  PRIMARY KEY (`id`(4)),
)

また、接頭辞(4)は、列の引用符の後に表示されます。

最後に、インデックスプレフィックスを使用する前に、インデックスプレフィックスがどのように機能するかとその制限を読む必要があります。

http://dev.mysql.com/doc/refman/5.0/en/create-index.html

18
Josh

特定のユースケースに依存します。

テーブルが静的で、値の短いリストしかない場合(そして、これがDBの存続期間中に変更される可能性がわずかにある場合)、この構造をお勧めします。

CREATE TABLE Foo 
(
    FooCode VARCHAR(16), -- short code or shortcut, but with some meaning.
    Name NVARCHAR(128), -- full name of entity, can be used as fallback in case when your localization for some language doesn't exist
    LocalizationCode AS ('Foo.' + FooCode) -- This could be a code for your localization table... 
)

もちろん、テーブルがまったく静的でない場合は、[〜#〜] int [〜#〜]を主キーとして使用するのが最適なソリューションです。

2
Tomino

データ入力エラーを回避するため、またはクーペンコードの更新などに使用できるように、このコンテキストではプライマリキーの代わりに一意を使用することが好ましいでしょう。

0
Imran Younas

確かに大丈夫です。わずか数百のエントリで、高速になります。

主キー(int autoincrement)として一意のIDを追加し、coupon_codeを一意に設定できます。したがって、他のテーブルでリクエストを行う必要がある場合は、varcharよりもintを使用することをお勧めします

0
guikk