You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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, description text not null, questions json not null, max_p...' at line 1 (Connection: mysql, SQL: create table polls (id bigint unsigned not null auto_increment primary key,created_at timestamp null,updated_at timestamp null,title varchar(255) not null,slug varchar(255) not null aftertitle, description text not null,questions json 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字段定义的语法规则。
  • 修正步骤:
    1. 调整slug字段的链式调用顺序,将after('title')移至字段类型定义之后、约束之前,确保生成正确的SQL字段位置和约束。
    2. 优化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)的语法糖,作用完全一致,但可读性更强。

内容的提问来源于stack exchange,提问作者Armando_pagano

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 19:17:41