假设我在Laravel中有一个父表和一个子表用于表Order
,我的模型看起来像这样:
public function up()
{
Schema::create('orders', function(Blueprint $table)
{
$table->integer('customer_id')->unsigned();
$table->foreign('customer_id')->references('id')->on('customers')->onDelete('cascade');
$table->increments('id');
我知道Eloquent会认为id
是orders
的主键,因此会在该主键上自动创建索引。
我应该怎么做才能确保customer_id
是主键索引的一部分,按顺序设置:
1. customer_id
2. id
表格示例
Customer
+-------------+
| id | --> primary key
|- - - - - - -|
| name |
| address |
+-------------+
|
|
|
A
Order
+------------------+
| customer_id (fk) | --- primary key
| id | --- primary key
|- - - - - - - - - |
| date |
+------------------+
答案 0 :(得分:2)
Eloquent会自动将此外键添加到主键的索引中吗?
嗯,不是自动的,但很容易。
要指定自定义主键,可以从Blueprint类调用primary()
方法,通过$ table调用。即$ table-> primary()。
对于单个主键,它接受一个字符串,指定要成为主键的列的名称。
对于复合键,您可以传递要成为主要列的字符串数组。在你的情况下
$table->primary(
['id', 'customer_id']
)
答案 1 :(得分:0)
我决定尝试一下,看看会发生什么。
从customers表开始,我运行了这个声明......
CREATE TABLE customers (
id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255),
created_at DATETIME,
updated_at DATETIME,
PRIMARY KEY (id)
);
然后我创建了以下内容......
CREATE TABLE orders (
id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
customer_id INT(11) UNSIGNED,
created_at DATETIME,
updated_at DATETIME,
PRIMARY KEY (id, customer_id)
);
请注意,如果您使用PRIMARY KEY (customer_id, id)
,则会导致SQL错误。这让我相信你试图复制的DB2功能在MySQL上的工作方式不一样,我们实际上需要一个外键。
然后在用测试数据填充这些表之后,我运行了以下内容......
EXPLAIN SELECT *
FROM customers
INNER JOIN orders ON customers.id = orders.customer_id;
这导致
+------+-------------+-----------+------+---------------+------+---------+------+--------+-------------------------------------------------+
| id | select_type | TABLE | TYPE | possible_keys | KEY | key_len | ref | ROWS | Extra |
+------+-------------+-----------+------+---------------+------+---------+------+--------+-------------------------------------------------+
| 1 | SIMPLE | customers | ALL | PRIMARY | NULL | NULL | NULL | 4 | |
| 1 | SIMPLE | orders | ALL | NULL | NULL | NULL | NULL | 262402 | USING WHERE; USING JOIN buffer (flat, BNL JOIN) |
+------+-------------+-----------+------+---------------+------+---------+------+--------+-------------------------------------------------+
然后我添加了外键......
ALTER TABLE orders ADD FOREIGN KEY customer_id (customer_id) REFERENCES customers (id) ON DELETE CASCADE ON UPDATE CASCADE;
使用相同的确切数据运行相同的解释查询之前,我现在得到结果......
+------+-------------+-----------+------+---------------+-------------+---------+-----------------------+-------+-------+
| id | select_type | TABLE | TYPE | possible_keys | KEY | key_len | ref | ROWS | Extra |
+------+-------------+-----------+------+---------------+-------------+---------+-----------------------+-------+-------+
| 1 | SIMPLE | customers | ALL | PRIMARY | NULL | NULL | NULL | 4 | |
| 1 | SIMPLE | orders | ref | customer_id | customer_id | 4 | cookbook.customers.id | 43751 | |
+------+-------------+-----------+------+---------------+-------------+---------+-----------------------+-------+-------+
正如您所看到的,当我添加外键时,正在评估的行数要少得多,这正是我们正在寻找的。令我感到惊讶的可能是因为我不是DBA,运行以下内容会产生相同的结果......
EXPLAIN SELECT * FROM orders WHERE customer_id = 4;
即使在这种情况下,复合主键也不会为你做任何事情,但外键正在帮助你。
尽管如此,我认为放弃复合主键并将id
设置为主键并将customer_id
设置为外键是安全的。这也为您提供了级联删除和更新的好处。