Laravel自定义表迁移失败,SQL语法错误求助
在Laravel中执行自定义MySQL迁移时遇到SQL语法错误,默认生成的迁移可正常运行,但polls表的迁移失败。
迁移代码如下:
return new class extends Migration { /** * Run the migrations. */ public function up(): void { Schema::create('polls', function (Blueprint $table) { $table->id(); $table->timestamps(); $table->string('title')->nullable(false); $table->string('slug')->unique()->after('title')->nullable(false); $table->text('description')->nullable(false); $table->json('questions'); $table->integer('max_points', false, true); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('polls'); } };
执行php artisan migrate时出现错误:
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'after
title,descriptiontext not null,questionsjson not null,max_p...' at line 1 (Connection: mysql, SQL: create tablepolls(idbigint unsigned not null auto_increment primary key,created_attimestamp null,updated_attimestamp null,titlevarchar(255) not null,slugvarchar(255) not null aftertitle,descriptiontext not null,questionsjson not null,max_points` int unsigned not null) default character set utf8mb4 collate 'utf8mb4_unicode_ci')
错误指向迁移文件第14行。
- 核心问题:链式调用方法顺序错误,
after('title')的位置导致生成的SQL语法不符合MySQL/MariaDB规范。生成的SQL中after被放在not null之后,且unique约束丢失,违反了SQL字段定义的语法规则。 - 修正步骤:
- 调整
slug字段的链式调用顺序,将after('title')移至字段类型定义之后、约束之前,确保生成正确的SQL字段位置和约束。 - 优化
max_points字段的写法,使用更直观的unsignedInteger方法替代integer的参数写法,提升代码可读性。
- 调整
修正后的迁移代码:
return new class extends Migration { /** * Run the migrations. */ public function up(): void { Schema::create('polls', function (Blueprint $table) { $table->id(); $table->timestamps(); $table->string('title'); // 默认即为非空,可省略nullable(false) $table->string('slug')->after('title')->unique(); // 调整顺序,默认非空 $table->text('description'); // 默认即为非空,可省略nullable(false) $table->json('questions')->nullable(false); // 明确指定非空(按需保留) $table->unsignedInteger('max_points'); // 替代原写法,更直观 }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('polls'); } };
- 补充说明:
- Laravel中
string()、text()方法默认都是非空(nullable(false)),可省略该调用简化代码。 after()方法用于指定字段在表中的位置,必须放在字段类型定义之后、约束(如unique())之前,才能生成正确的SQL语法。unsignedInteger()是integer($column, false, true)的语法糖,作用完全一致,但可读性更强。
- Laravel中
内容的提问来源于stack exchange,提问作者Armando_pagano

