Laravel - 迁移,table 结构修改 - 正确方法
Laravel - migration, table structure modification - correct way
我现在的table是
Schema::create('students', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('first_name', 255);
$table->string('last_name', 255);
$table->enum('gender', ['m', 'f']);
$table->date('date_of_birth');
$table->integer('roll_number');
$table->char('section', 1);
$table->integer('class');
$table->unsignedBigInteger('school_id');
$table->string('photo')->nullable;
$table->timestamps();
$table->foreign('school_id')
->references('id')->on('schools')
->onUpdate('cascade')->onDelete('cascade');
$table->unique(['roll_number', 'section', 'class', 'school_id']);
});
标准
Schema::create('standards', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->unsignedBigInteger('school_id');
$table->timestamps();
$table->foreign('school_id')
->references('id')->on('schools')
->onUpdate('cascade')->onDelete('cascade');
});
栏目
Schema::create('sections', function (Blueprint $table) {
$table->bigIncrements('id');
$table->char('name', 1);
$table->unsignedBigInteger('standard_id');
$table->timestamps();
$table->foreign('standard_id')
->references('id')->on('standards')
->onUpdate('cascade')->onDelete('cascade');
});
现在我有标准和部分 table,这些 table 中的外键将替换现有结构中的 class 和部分列,并保持 [=17= 的组合]、section_id
、standard_id
和 school_id
作为唯一。
我试过了
public function up()
{
Schema::table('students', function (Blueprint $table) {
$table->dropUnique(['roll_number', 'section', 'class', 'school_id']);
$table->dropColumn('section');
$table->dropColumn('class');
$table->unsignedBigInteger('standard_id')->after('roll_number');
$table->unsignedBigInteger('section_id')->after('standard_id');
$table->foreign('standard_id')->references('id')->on('standards')
->onUpdate('cascade')->onDelete('cascade');
$table->foreign('section_id')->references('id')->on('sections')
->onUpdate('cascade')->onDelete('cascade');
$table->unique(['roll_number', 'standard_id', 'section_id', 'school_id']); // unique combination
});
}
但它似乎不起作用。
错误
Illuminate\Database\QueryException : SQLSTATE[23000]: Integrity
constraint violation: 1452 Cannot add or update a child row: a foreign
key constraint fails (myapp_extra
.#sql-2f78_29d
, CONSTRAINT
students_standard_id_foreign
FOREIGN KEY (standard_id
) REFERE
NCES standards
(id
) ON DELETE CASCADE ON UPDATE CASCADE) (SQL: alter table students
add constraint students_standard_id_foreign
foreign key (standard_id
) references standards
(id
) on delete
cascade on update cascade)
at \myapp\vendor\laravel\framework\src\Illuminate\Database\Connection.php:664
注意:标准和部分 table 是在进行此迁移之前创建的,因此两列都可用。
为什么会这样?
发生此错误是因为您正在向已有行的 table 插入一个没有默认值且没有 NULLABLE
的新列。
当您这样做时,MySQL 会将其值设置为 0
,因此您所有的 table 都将 standard_id
和 section_id
设置为0
,所以当您尝试添加您的外部索引时,它会失败,因为 0
不是您 standards
/sections
table.[= 上的有效 ID 21=]
那么如何解决?
你有一些方法可以解决这个问题:
第一步:设置默认值
如果对您的应用程序有意义,您可以为您的列设置一个默认(有效)值,这样外键就不会失效:
$table->unsignedBigInteger('standard_id')->default(1)->after('roll_number');
$table->unsignedBigInteger('section_id')->default(1)->after('standard_id');
大多数时候不是那么简单,因此您需要动态定义值
第二:动态设置值
如果您有一些逻辑来为此新列设置默认值,则可以将迁移分为两个步骤:
// Add the fields first
Schema::table('students', function (Blueprint $table) {
$table->dropUnique(['roll_number', 'section', 'class', 'school_id']);
$table->dropColumn('section');
$table->dropColumn('class');
$table->unsignedBigInteger('standard_id')->after('roll_number');
$table->unsignedBigInteger('section_id')->after('standard_id');
}
App\Students::get()->each(function($student) {
// Apply your logic here
$student->standard_id = 3;
$student->section_id = 3;
$student->save();
});
// Now you can add your foreign keys.
Schema::table('students', function (Blueprint $table) {
$table->foreign('standard_id')->references('id')->on('standards')
->onUpdate('cascade')->onDelete('cascade');
$table->foreign('section_id')->references('id')->on('sections')
->onUpdate('cascade')->onDelete('cascade');
$table->unique(['roll_number', 'standard_id', 'section_id', 'school_id']); // unique combination
});
第三:使字段可为空
如果您只是不知道或没有此字段的默认值,那么您的字段应该可以为空:
$table->unsignedBigInteger('standard_id')->nullable()->after('roll_number');
$table->unsignedBigInteger('section_id')->nullable()->after('standard_id');
我现在的table是
Schema::create('students', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('first_name', 255);
$table->string('last_name', 255);
$table->enum('gender', ['m', 'f']);
$table->date('date_of_birth');
$table->integer('roll_number');
$table->char('section', 1);
$table->integer('class');
$table->unsignedBigInteger('school_id');
$table->string('photo')->nullable;
$table->timestamps();
$table->foreign('school_id')
->references('id')->on('schools')
->onUpdate('cascade')->onDelete('cascade');
$table->unique(['roll_number', 'section', 'class', 'school_id']);
});
标准
Schema::create('standards', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->unsignedBigInteger('school_id');
$table->timestamps();
$table->foreign('school_id')
->references('id')->on('schools')
->onUpdate('cascade')->onDelete('cascade');
});
栏目
Schema::create('sections', function (Blueprint $table) {
$table->bigIncrements('id');
$table->char('name', 1);
$table->unsignedBigInteger('standard_id');
$table->timestamps();
$table->foreign('standard_id')
->references('id')->on('standards')
->onUpdate('cascade')->onDelete('cascade');
});
现在我有标准和部分 table,这些 table 中的外键将替换现有结构中的 class 和部分列,并保持 [=17= 的组合]、section_id
、standard_id
和 school_id
作为唯一。
我试过了
public function up()
{
Schema::table('students', function (Blueprint $table) {
$table->dropUnique(['roll_number', 'section', 'class', 'school_id']);
$table->dropColumn('section');
$table->dropColumn('class');
$table->unsignedBigInteger('standard_id')->after('roll_number');
$table->unsignedBigInteger('section_id')->after('standard_id');
$table->foreign('standard_id')->references('id')->on('standards')
->onUpdate('cascade')->onDelete('cascade');
$table->foreign('section_id')->references('id')->on('sections')
->onUpdate('cascade')->onDelete('cascade');
$table->unique(['roll_number', 'standard_id', 'section_id', 'school_id']); // unique combination
});
}
但它似乎不起作用。
错误
Illuminate\Database\QueryException : SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (
myapp_extra
.#sql-2f78_29d
, CONSTRAINTstudents_standard_id_foreign
FOREIGN KEY (standard_id
) REFERE NCESstandards
(id
) ON DELETE CASCADE ON UPDATE CASCADE) (SQL: alter tablestudents
add constraintstudents_standard_id_foreign
foreign key (standard_id
) referencesstandards
(id
) on delete cascade on update cascade)at \myapp\vendor\laravel\framework\src\Illuminate\Database\Connection.php:664
注意:标准和部分 table 是在进行此迁移之前创建的,因此两列都可用。
为什么会这样?
发生此错误是因为您正在向已有行的 table 插入一个没有默认值且没有 NULLABLE
的新列。
当您这样做时,MySQL 会将其值设置为 0
,因此您所有的 table 都将 standard_id
和 section_id
设置为0
,所以当您尝试添加您的外部索引时,它会失败,因为 0
不是您 standards
/sections
table.[= 上的有效 ID 21=]
那么如何解决?
你有一些方法可以解决这个问题:
第一步:设置默认值
如果对您的应用程序有意义,您可以为您的列设置一个默认(有效)值,这样外键就不会失效:
$table->unsignedBigInteger('standard_id')->default(1)->after('roll_number');
$table->unsignedBigInteger('section_id')->default(1)->after('standard_id');
大多数时候不是那么简单,因此您需要动态定义值
第二:动态设置值
如果您有一些逻辑来为此新列设置默认值,则可以将迁移分为两个步骤:
// Add the fields first
Schema::table('students', function (Blueprint $table) {
$table->dropUnique(['roll_number', 'section', 'class', 'school_id']);
$table->dropColumn('section');
$table->dropColumn('class');
$table->unsignedBigInteger('standard_id')->after('roll_number');
$table->unsignedBigInteger('section_id')->after('standard_id');
}
App\Students::get()->each(function($student) {
// Apply your logic here
$student->standard_id = 3;
$student->section_id = 3;
$student->save();
});
// Now you can add your foreign keys.
Schema::table('students', function (Blueprint $table) {
$table->foreign('standard_id')->references('id')->on('standards')
->onUpdate('cascade')->onDelete('cascade');
$table->foreign('section_id')->references('id')->on('sections')
->onUpdate('cascade')->onDelete('cascade');
$table->unique(['roll_number', 'standard_id', 'section_id', 'school_id']); // unique combination
});
第三:使字段可为空
如果您只是不知道或没有此字段的默认值,那么您的字段应该可以为空:
$table->unsignedBigInteger('standard_id')->nullable()->after('roll_number');
$table->unsignedBigInteger('section_id')->nullable()->after('standard_id');