Laravel 将自动将此外键添加到主键';s指数?
假设我有一个父表和一个子表,在Laravel中,对于表Laravel 将自动将此外键添加到主键';s指数?,laravel,laravel-5,eloquent,Laravel,Laravel 5,Eloquent,假设我有一个父表和一个子表,在Laravel中,对于表顺序,我的模型如下所示: public function up() { Schema::create('orders', function(Blueprint $table) { $table->integer('customer_id')->unsigned(); $table->foreign('customer_id')->references('id')->
顺序
,我的模型如下所示:
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');
< P> >我知道雄辩者会认为<代码> ID>代码>是customer\u id
是主键索引的一部分,设置顺序如下:
1. customer_id
2. id
表格示例
Customer
+-------------+
| id | --> primary key
|- - - - - - -|
| name |
| address |
+-------------+
|
|
|
A
Order
+------------------+
| customer_id (fk) | --- primary key
| id | --- primary key
|- - - - - - - - - |
| date |
+------------------+
Eloquent会自动将此外键添加到主键的索引中吗
嗯,不是自动的,但很容易
要指定自定义主键,可以从Blueprint类调用primary()
方法,通过$table调用。ie$table->primary()
对于单个主键,它接受一个字符串,该字符串指定要成为主键的列的名称
对于复合键,您可以传递要设为主的列的字符串数组。就你而言
$table->primary(
['id','customer\u id']
)
Eloquent会自动将此外键添加到主键的索引中吗
嗯,不是自动的,但很容易
要指定自定义主键,可以从Blueprint类调用primary()
方法,通过$table调用。ie$table->primary()
对于单个主键,它接受一个字符串,该字符串指定要成为主键的列的名称
对于复合键,您可以传递要设为主的列的字符串数组。就你而言
$table->primary(
['id','customer\u id']
)
我决定尝试一下,看看会发生什么
从客户表开始,我运行了以下语句
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)
);
EXPLAIN SELECT *
FROM customers
INNER JOIN orders ON customers.id = orders.customer_id;
注意:如果使用主键(customer\u id,id)
,将导致SQL错误。这让我相信,您尝试复制的DB2功能在MySQL上的工作方式不会完全相同,我们实际上需要一个外键
然后在用测试数据填充这些表之后,我运行以下程序
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)
);
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 | |
+------+-------------+-----------+------+---------------+-------------+---------+-----------------------+-------+-------+
EXPLAIN SELECT * FROM orders WHERE customer_id = 4;
正如您所看到的,当我添加外键时,计算的行要少得多,这正是我们要寻找的。让我惊讶的可能是因为我不是DBA,运行以下命令会产生相同的结果
+------+-------------+-----------+------+---------------+-------------+---------+-----------------------+-------+-------+
| 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 | |
+------+-------------+-----------+------+---------------+-------------+---------+-----------------------+-------+-------+
EXPLAIN SELECT * FROM orders WHERE customer_id = 4;
即使在这种情况下,复合主键也不会为您做任何事情,但是外键起到了巨大的作用
综上所述,我认为放弃复合主键是安全的,只需将
id
设置为主键,并将customer\u id
设置为外键。这也使您能够级联删除和更新。我决定尝试一下,看看会发生什么
从客户表开始,我运行了以下语句
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)
);
EXPLAIN SELECT *
FROM customers
INNER JOIN orders ON customers.id = orders.customer_id;
注意:如果使用主键(customer\u id,id)
,将导致SQL错误。这让我相信,您尝试复制的DB2功能在MySQL上的工作方式不会完全相同,我们实际上需要一个外键
然后在用测试数据填充这些表之后,我运行以下程序
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)
);
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 | |
+------+-------------+-----------+------+---------------+-------------+---------+-----------------------+-------+-------+
EXPLAIN SELECT * FROM orders WHERE customer_id = 4;
正如您所看到的,当我添加外键时,计算的行要少得多,这正是我们要寻找的。让我惊讶的可能是因为我不是DBA,运行以下命令会产生相同的结果
+------+-------------+-----------+------+---------------+-------------+---------+-----------------------+-------+-------+
| 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 | |
+------+-------------+-----------+------+---------------+-------------+---------+-----------------------+-------+-------+
EXPLAIN SELECT * FROM orders WHERE customer_id = 4;
即使在这种情况下,复合主键也不会为您做任何事情,但是外键起到了巨大的作用
综上所述,我认为放弃复合主键是安全的,只需将
id
设置为主键,并将customer\u id
设置为外键。这还使您能够级联删除和更新。尝试添加$table->primary(数组('id','customer\u id')代码>!请参阅下面的链接。我希望它能帮助你。是否有理由需要它作为主键索引的一部分?这对我来说没什么意义。如果您只是在寻找有效的联接,外键应该足够了,您可以通过执行解释选择…
来验证它。我的想法是,当我使用客户id
查询订单表时,MySQL通过主键索引(客户id,id)访问订单会更快,因为customer\u id
将是主键索引的第一列。我曾经在DB2上工作过,并且是这样做的,但我猜MySQL的做法有所不同?尝试添加$table->primary(数组('id','customer_id')代码>!请参阅下面的链接。我希望它能帮助你。是否有理由需要它作为主键索引的一部分?这对我来说没什么意义。如果您只是在寻找有效的联接,外键应该足够了,您可以通过执行解释选择…
来验证它。我的想法是,当我使用客户id
查询订单表时,MySQL通过主键索引(客户id,id)访问订单会更快,因为customer\u id
将是主键索引的第一列。我曾经在DB2上工作过,并且是这样做的,但我猜MySQL的做法有所不同?我尝试过$table->primary(['id','customer\u id')代码>,它可以工作,但我想要的是$table->primary(['customer\u id','id')
因为当我使用客户id
进行查询时,索引查找订单会更快,但Eloquent不允许我这样做。我收到以下消息:SQLSTATE[42000]:语法错误或acc