データベースのテーブル設計における主キーについて

このQ&Aのポイント
  • データベースのテーブル設計において、マスタを物理削除せず、論理削除する場合、削除日時を主キーに持ってくることは一般的な方法です。
  • 主キーにNULL値は入れられないため、削除日時を無理やりNULL以外の値で設定することがあります。アプリケーションで削除になっていないレコードを検索する際に、削除日時を使用することが多いです。
  • 削除日時を主キーに持ってくることで、削除されていないレコードを効率的に検索することができます。ただし、削除日時の値が頻繁に変更される場合は、インデックスの効果が低下する可能性があります。
回答を見る
  • ベストアンサー

テーブル設計の主キーについて質問があります。

テーブル設計の主キーについて質問があります。 マスタを物理削除せず、論理削除するデータベースを考える時、 削除日時を主キーに持ってきたりするレイアウトはよくありますでしょうか。 DBはmysqlです。 例) <会社マスタ> (PK)会社コード (PK)会社支店コード (PK)削除日時    会社名    住所 主キーにNULL値は入れられないと思うのですが(←あっていますでしょうか)、 削除日時を無理やりNULL以外のものを入れたとします。 そしてアプリケーションで検索を考えた時に、”削除になっていないもの” を対象にレコードを探します。 インデックス(この場合は主キーですが)が検索高速化に有効に使われるのは、 なるべく対象が少なくなるものと思います。 以上を考えれば、 割合が多い削除日時を主キーにもってくるのはいかがなものかと思うのですが、 どうなのでしょうか。 宜しくアドバイスお願いいたします。

  • MySQL
  • 回答数2
  • ありがとう数17

質問者が選んだベストアンサー

  • ベストアンサー
  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.1

構造が今一つわかりませんが、この場合でも削除日時はプライマリキーに すべきではないでしょう。 仮に削除日時をプライマリの要素にまぜると、たとえばA社東京支店があったとして 削除日2010/1/1のA社東京支店と、削除日2010/2/1のA社東京支店が存在可能になります。 やはりA社東京支店のみをプライマリとするのが管理上常套かとおもいます。 今回の場合は、削除日時にインデックスを貼っておくか、削除フラグフィールドを つくっておくかがよいでしょう

hanahana1234
質問者

お礼

ありがとうございます! 自分でもそのような設計は見たことなかったのですが、 既存システムではそうしてたようで、自分だけが知らないのかなと思っていました。 アドバイスどうもありがとうございました。 確信がもてました。

その他の回答 (1)

  • kotoby2003
  • ベストアンサー率15% (280/1755)
回答No.2

削除日時を主キーにするのは明らかにおかしいです。なんのためでしょう。 インデックスを張るだけでよいと思います。 削除日時を主キーにしてしまうと、同じ会社コード、会社支店コードのものが複数存在してしまうことになります。

hanahana1234
質問者

お礼

ありがとうございます! 自分でもそのような設計は見たことなかったのですが、 既存システムではそうしてたようで、自分だけが知らないのかなと思っていました。 アドバイスどうもありがとうございました。 確信がもてました。

関連するQ&A

  • ACCESSにインデックス(主キー)のあるテーブルを作りたい

    元データがEXCELでそのデータを利用し、 ACCESS内にマスター用(品目マスタ)のテーブルを作り、 1番目の部品コードというフィールドを インデックス/主キー(重複しない)にして 2番目、3番目の項目の値をえられるように しようとしていますが、EXCELからの元データを インポートしようとしても部品コードフィールドが インデックス/主キーに設定できません。 EXCEL内で部品コードが重複しないように削った つもりです。 部品コードが重複していなくても、いけない文字列 があってインデックス/主キーにできないのでしょうか? ※詳細 以下のようなテーブルをつくり、 284-A80と入力したら製品部品名称の「基板」と いう値や製品分類の「LED」という値を得ようと している。 部品コード    製品部品名称   製品分類 284-A80      基板        LED 7841P20      ヨーク       ブザー CL-270-CD     LED         LED HSDL-3201#001   センサー     センサー ……約17000レコードぐらい ただし、部品コードの値がもっとごちゃごちゃして いて、「*」、「スペース」「#」「_」「/」などや カタカナ文字のものも含まれていたりします。 なぜ、上記の部品コードをインデックス/主キーとして 設定をおこなったテーブルとしてインポート できないのですか?

  • 【初歩】 主キー&ユニーク&AUTO_INCREMENTをつけたフィールドを作りたい

    ・WindowsXP(SP2)IIS5.1 ・PHP 5.2.5 Win32 ・MySQL 5.1.22 RC Win32 ・phpMyAdmin 2.11.4 会社マスター(KAISYA)に管理番号、Eメール、氏名、備考、更新日時とあります。これらのうち、 ・「管理番号」に、主キー、ユニーク制約、AUTO_INCREMENTを。 ・「Eメール」に、主キー、ユニーク制約を それぞれつけるにはどのようなSQL文を発行したらいいかご教示ください。 phpMyAdminで発行した下記のSQL文ですと、 CREATE TABLE IF NOT EXISTS `KAISYA` ( `KanriNo` int unsigned AUTO_INCREMENT COMMENT '管理番号', `Email` varchar( 80 ) NOT NULL default '' COMMENT 'Eメール', `Namae` varchar( 40 ) default NULL COMMENT '氏名', `Bikou` text COMMENT '備考', `UpdateDate` timestamp NOT NULL default '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP COMMENT '更新日時' ) ENGINE = InnoDB DEFAULT CHARSET = utf8 #1075 - Incorrect table definition; there can be only one auto column and it must be defined as a key とエラーになってしまいます。 (このSQL例文には、主キー、ユニーク制約の件は未反映です) `KanriNo` int ....の行を削除すればSQL は正常に実行されるのですが。

    • ベストアンサー
    • MySQL
  • 漢字名のテーブルとカラムのCREATE TABLEについて

    Oracle9iで以下のCREATE文を実行しようと思っています。 漢字名のテーブルで、漢字名のカラムのあるCREATE文です。 SQL> CREATE TABLE "TAB_あいう"( 2 "かきコード" varchar2(5) NOT NULL , 3 "くけ開始月" varchar2(2) NOT NULL , 4 "フラグ" char(1) NOT NULL , 5 "さCD" char(6) NOT NULL , 6 "日時" date NOT NULL , 7 canstraint PK_FISCALTERM primary key ("かきコード")); canstraint PK_FISCALTERM primary key ("かきコード"))                            * 行7でエラーが発生しました。: ORA-00907: 右カッコがありません。 しかし、 ORA=00907;右カッコがありません。といわれてしまいます。 見た目、右かっこはあります。 なにか、お作法的なものがあるのでしょうか?

  • CREATE テーブルでの複数外部キーの設定

    MySQL5.1で、1つの表に複数の外部キーを持つとき、 CREATEテーブル発行の仕方について教えてください。 1、以下表3つ作成 得意先表 {得意先コード(主),得意先名} 注文表 {年月日,得意先コード(外),商品コード(外),数量} ※得意先コード、商品コードに、on delete cascadeをつける。 商品表 {商品コード(主),商品名,商品区分コード(外),単価} の三つの表があります。 質問)、注文表に、2つの外部キー(得意先コード・商品コード)を設定したいと思っています。 CREATE TABLE IF NOT EXISTS `注文表` ( `注文日` date DEFAULT NULL, `得意先コード` varchar(10) DEFAULT NULL REFERENCES 得意先表(得意先コード) on delete cascade, `商品コード` varchar(10) DEFAULT NULL REFERENCES 商品表(商品コード) on delete cascade, `数量` int(11) DEFAULT NULL ) の外部キーを列制約で作成するのがいいのでしょうか? 表制約では、二つの外部キーを設定できないと思いましたので・・・。 ご教授お願いします。

  • テーブルの主キー採番を標準モジュールで行いたい!

    テーブルの主キー採番を標準モジュールで行いたい! 現在下記のコードで各フォームより各テーブルに番号を振っているのですが、 1.新規登録ボタンクリック時 2.削除ボタンクリック時など 同じコードを記述しなければいけないのでFunctionプロシージャで各フォームのコマンドボタンのクリック時に各テーブルに採番したいと思うのですが良い方法がありましたらアドバイス宜しくお願いいたします。 If DCount("*", "T会社") = 0 Then Forms("F会社").txt会社コード = "001" Else Forms("F会社").txt会社コード = _ Format(DMax("会社コード", "T会社") + 1, "000") End If

  • varchar型を主キーに…

    現在サーブレット/JSPを利用してDBにユーザアカウントを登録、削除、更新、一覧をできるようするシステムを作成しています。 テーブルを create table loginuser ( userId char(16) not null default '', passwd char(16) not null default '', name varchar(50) not null default '', accessFlg int(1) not null default '0', primary key(userId)); で作成しました。 IDが数字の時はDBに登録ができるのですがIDに文字を入力するとDBに登録されません。 主キーをvarchar型で使用するのは不可能なのでしょうか? ご返答をよろしくお願いします。

  • データベースの設計について教えてください。

    データベースの設計について教えてください。 基本的な質問ですみません。宜しくお願いいたします。 単純なテーブルで表現しますが、 パターンA、Bのどちらのテーブルで設計するのが良いのでしょうか。 DBはmysqlで5000万件のデータで検索のみのデータベースです。 【前提】 ユーザは複数のメールアドレスを持ちます。 画面から、このユーザのもつメールアドレスを表示させる仕様だとします。 【userマスタ】 (PK)ユーザID   ユーザ名   会社名 <パターンA> 【mailテーブル】 (PK)ユーザID (PK)ユーザメールアドレス   モバイル用アドレス <パターンB>  【mailテーブル】 (PK)ユーザメールアドレス   モバイル用アドレス   ユーザID ←インデックスをはります。

    • ベストアンサー
    • MySQL
  • テーブルに空文字を入力させない方法

    MYSQLで下記のようなテーブルがあります。codeが主キーになっています。 +---------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+--------------+------+-----+---------+-------+ | day | varchar(255) | YES | | NULL | | | time_mm | varchar(255) | YES | | NULL | | | time_ss | varchar(255) | YES | | NULL | | | id | varchar(255) | YES | | NULL | | | code | varchar(255) | NO | PRI | NULL | | | stock | varchar(255) | YES | | NULL | | +---------+--------------+------+-----+---------+-------+ selectでデータを引っ張ってくると下記のようになります。 +------+---------+---------+-------+------+-------+ | day | time_mm | time_ss | id | code | stock | +------+---------+---------+-------+------+-------+ | NULL | NULL | NULL | dd | | NULL | | 1111 | 2222 | 3333 | 4444 | 1234 | 6666 | | 11 | 22 | 33 | 44 | 4649 | 66 | | 111 | 222 | 333 | 444 | 5963 | 666 | | NULL | NULL | fdfd | fdfd | fd | NULL | +------+---------+---------+-------+------+-------+ codeの一番上が空文字列になっているので、テーブルにデータが入っていると思うのですが、空文字も入力不可にさせたいです。 どのようにすれば実現させることができるでしょうか?

  • ACCESS標準モジュールでテーブルの主キー採番したい。

    ACCESS標準モジュールでテーブルの主キー採番したい。 フォームが (1) [Fメインメニュー] (2) [F会社] "(1)(2)全て非連結のtxtbox" と2つあり、(1)のコマンドボタンから(2)のフォームを開く時に (2)のtxtboxに現在下記のコードで採番しています。 If DCount("*", "T会社") = 0 Then Forms("F会社").txt会社コード = "001" Else Forms("F会社").txt会社コード = _ Format(DMax("会社コード", "T会社") + 1, "000") End If これを標準モジュールで行いたいのですが、良い方法を教えて下さい。 宜しくお願いいたします。

  • データベース:主キーが文字列の場合IDを振るべき?

    テーブルの主キーが文字列の場合、 その主キーの文字列を通し番号に置き換えて、 その文字列は別テーブルに移したほうが検索が速いですか? 例えば、テーブルが CREATE TABLE spec ( test_name VARCHAR(40) NOT NULL, upper_limit NUMERIC(17,7), lower_limit NUMERIC(17,7), PRIMARY KEY(test_name) ); で、40文字という長いテスト項目名の場合、 CREATE TABLE spec ( test_id INTEGER NOT NULL, upper_limit NUMERIC(17,7), lower_limit NUMERIC(17,7), PRIMARY KEY(test_id) ); と CREATE TABLE test ( test_id INTEGER NOT NULL, test_name VARCHAR(40) NOT NULL, PRIMARY KEY(test_id) ); という二つのテーブルに分けたほうが検索は速くなりますか? (もちろん、結合する時間も含めてです。) もし速くなるとしても、文字数が3文字など少ない場合は 通し番号に置き換えてもきっと効果は薄いですよね? 何文字以上の文字列なら通し番号に置き換えたほうが速いですか? 皆さんはどのように決めていますか?