1

結合テーブルを使用する CakePHP フレームワーク用のアプリケーションを作成しました。

SQL の最初のブロックに示されているように、結合テーブルの各行を一意に識別するために主キーが必要かどうかはわかりません。

2 つのフィールドを一意のキーとして設定する必要がありますか、それとも両方を主キーとして設定し、id を主キーとして削除することはできますか?

また、列制約ではなくテーブル制約を使用してアトミック主キーを宣言する理由も尋ねられましたが、これは、結合テーブルに一意のキーを設定すべきではないということですか?

CREATE TABLE IF NOT EXISTS `categories_invoices` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `category_id` int(11) NOT NULL,
  `invoice_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `category_id` (`category_id`,`invoice_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=163 ;

ここに示すように、解決策はおそらく両方のキーを一意に設定し、主キーを削除することだと考えていました:

 CREATE TABLE IF NOT EXISTS `categories_invoices` (
      `category_id` int(11) NOT NULL,
      `invoice_id` int(11) NOT NULL,
      UNIQUE KEY `category_id` (`category_id`,`invoice_id`)
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1;

実際、結合テーブルの主キー「id」を削除して、「category_id」と「invoice_id」のみを残してテストしましたが、アプリケーションは引き続き機能しました。これにより、両方のフィールドが結合テーブル内の一意のフィールドとして残ります。これは実際に正しい習慣ですか?

4

2 に答える 2

6

両方は必要ありません。複合一意キーは主キーを置き換えることができます (Cake フレームワークが複合 Priamry キーを処理できない場合を除きます):

 CREATE TABLE IF NOT EXISTS categories_invoices (
      category_id int(11) NOT NULL,
      invoice_id int(11) NOT NULL,
      PRIMARY KEY (category_id, invoice_id)
    ) 
    ENGINE = MyISAM 
    DEFAULT CHARSET = latin1 ;

主キー用に作成されたインデックスの他に、逆の順序で別のインデックスを作成することもお勧めします。

   INDEX (invoice_id, category_id)

外部キー制約を定義する場合は、InnoDBエンジンを使用する必要があります。外部キーを持つことMyISAMはできません。したがって、次のようになります。

 CREATE TABLE IF NOT EXISTS categories_invoices (
      category_id int(11) NOT NULL,
      invoice_id int(11) NOT NULL,
      PRIMARY KEY (category_id, invoice_id),
      INDEX invoice_category_index (invoice_id, category_id)
    ) 
    ENGINE = InnoDB  
    DEFAULT CHARSET=latin1 ;

Cake が複合主キーに対応できない場合:

 CREATE TABLE IF NOT EXISTS categories_invoices (
      id int(11) NOT NULL AUTO_INCREMENT,
      category_id int(11) NOT NULL,
      invoice_id int(11) NOT NULL,
      PRIMARY KEY (id),
      UNIQUE KEY category_invoice_unique (category_id, invoice_id),
      INDEX invoice_category_index (invoice_id, category_id)
    ) 
    ENGINE = InnoDB  
    DEFAULT CHARSET=latin1 ;
于 2012-05-05T13:12:39.690 に答える
2

2番目の方法に問題はありません。これは複合キーと呼ばれ、データベース設計、特に状況において非常に一般的です。

http://en.wikipedia.org/wiki/Relational_database#Primary_keys

于 2012-05-05T13:15:42.007 に答える