我已经为CakePHP框架创建了一个使用连接表的应用程序.
我不确定是否需要一个主键来uniquley标识连接表的每一行,如SQL的第一个块所示.
这两个字段是否需要设置为唯一键,还是可以将它们都设置为主键,我将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 ;
Run Code Online (Sandbox Code Playgroud)
我认为解决方案可能是将两个密钥设置为唯一,并删除主键,如下所示:
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;
Run Code Online (Sandbox Code Playgroud)
我确实测试了删除连接表的主键'id',只留下'category_id'和'invoice_id',应用程序仍然有用.这使得两个字段都作为连接表中的唯一字段.这实际上是正确的做法吗?
你不需要两者.复合唯一键可以替换主键(除非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 ;
Run Code Online (Sandbox Code Playgroud)
除了为主键创建的索引之外,还有另一个索引,顺序相反:
INDEX (invoice_id, category_id)
Run Code Online (Sandbox Code Playgroud)
如果要定义外键约束,则应使用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 ;
Run Code Online (Sandbox Code Playgroud)
如果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 ;
Run Code Online (Sandbox Code Playgroud)