为啥在区域表定义中未创建 state_id 字段?

Posted

技术标签:

【中文标题】为啥在区域表定义中未创建 state_id 字段?【英文标题】:Why state_id field is not create in regions table definition?为什么在区域表定义中未创建 state_id 字段? 【发布时间】:2021-12-10 06:19:30 【问题描述】:

我尝试将旧数据库从 laravel 5.x 重构为 laravel 8 并拥有 2 个相关表: 数据库/迁移/2019_05_21_144910_create_states_table.php

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;

class CreateStatesTable extends Migration 

   /**
    * Run the migrations.
    *
    * @return void
    */
   public function up()
   
      Schema::create('states', function(Blueprint $table)
      
            $table->smallIncrements('id')->unsigned();
            $table->string('code', 3)->unique();
         $table->string('name', 50)->unique();
         $table->string('slug', 55)->unique();
            $table->enum('active', ['A', 'I'])->default('I')->comment(' A=>Active, I=>Inactive');
         $table->index(['active','code'], 'fk_states_active_code_ixd');
         $table->index(['active','slug'], 'fk_states_active_slug_ixd');
      );
   


   /**
    * Reverse the migrations.
    *
    * @return void
    */
   public function down()
   
      Schema::drop('states');
   


和数据库/迁移/2019_05_21_145001_create_regions_table.php:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;

class CreateRegionsTable extends Migration


    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    
        Schema::create('regions', function (Blueprint $table) 

            $table->smallIncrements('id')->unsigned();

            $table->foreign('state_id')->references('id')->on('states')->onUpdate('RESTRICT')->onDelete('RESTRICT');


            $table->string('name', 50);
            $table->string('slug', 55)->unique();

            $table->enum('active', ['A', 'I'])->default('I')->comment(' A=>Active, I=>Inactive');

            $table->unique(['state_id', 'name']);

            $table->index(['state_id', 'active'], 'fk_regions_state_id_active_ixd');
        );
    


    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    
        Schema::drop('regions');
    


运行迁移命令时出错:

php artisan migrate:fresh --seed
...
Migrating: 2019_05_21_144910_create_states_table
Migrated:  2019_05_21_144910_create_states_table (626.91ms)
Migrating: 2019_05_21_145001_create_regions_table

   Illuminate\Database\QueryException 

  SQLSTATE[42000]: Syntax error or access violation: 1072 Key column 'state_id' doesn't exist in table (SQL: alter table `regions` add constraint `regions_state_id_foreign` foreign key (`state_id`) references `states` (`id`) on delete RESTRICT on update RESTRICT)

  at vendor/laravel/framework/src/Illuminate/Database/Connection.php:703
    699▕         // If an exception occurs when attempting to run a query, we'll format the error
    700▕         // message to include the bindings with SQL, which will make this exception a
    701▕         // lot more helpful to the developer instead of just the database's errors.
    702▕         catch (Exception $e) 
  ➜ 703▕             throw new QueryException(
    704▕                 $query, $this->prepareBindings($bindings), $e
    705▕             );
    706▕         
    707▕     

      +9 vendor frames 
  10  database/migrations/2019_05_21_145001_create_regions_table.php:31
      Illuminate\Support\Facades\Facade::__callStatic()

      +32 vendor frames 
  43  artisan:37
      Illuminate\Foundation\Console\Kernel::handle()

在区域表中,我有区域表,但没有 state_id 字段。看起来像线

$table->foreign('state_id')->references('id')->on('states')->onUpdate('RESTRICT')->onDelete('RESTRICT');

被忽略了,我无法理解为什么?试了好几次...

更新 2: 我将 CreateRegionsTable 修改为:

Schema::create('regions', function (Blueprint $table) 

    $table->smallIncrements('id')->unsigned();
   $table->foreignId('state_id')->constrained('states')->onUpdate('RESTRICT')->onDelete('RESTRICT');

但我遇到了其他错误:

  SQLSTATE[HY000]: General error: 3780 Referencing column 'state_id' and referenced column 'id' in foreign key constraint 'regions_state_id_foreign' are incompatible. (SQL: alter table `regions` add constraint `regions_state_id_foreign` foreign key (`state_id`) references `states` (`id`) on delete RESTRICT on update RESTRICT)

在 database/migrations/2019_05_21_144910_create_states_table.php 我有:

Schema::create('states', function(Blueprint $table)

    $table->smallIncrements('id')->unsigned();

我认为 foreignId 与 smallIncrements 不兼容...但哪种方法有效?

提前致谢!

【问题讨论】:

foreign 在现有列上添加约束。使用foreignId('state_id')-&gt;constrained() 创建列和外键索引。更多内容请关注docs 【参考方案1】:

$table-&gt;foreign() 方法仅将外键约束添加到现有列。你要找的方法是$table-&gt;foreignId()

所以而不是

$table->foreign('state_id')->references('id')->on('states')->onUpdate('RESTRICT')->onDelete('RESTRICT');

在您的区域表迁移中,您应该这样做

$table->foreignId('state_id')->constrained('states')->onUpdate('RESTRICT')->onDelete('RESTRICT');

documentation

【讨论】:

请看更新2 抱歉回复晚了。 $table-&gt;foreignId('state_id') 方法默认添加一个 bigInteger 数据类型列,而 $table-&gt;smallIncrements() 添加一个 smallInteger 数据类型列。您不能将外键约束添加到两个不同的数据类型列。您可以将 states 表的 id 列更改为 bigIncrements() 或在您的区域表中,首先为 state_id 创建一个 smallInteger() 列,然后为其添加外键约束。 请注意 smallInteger 列的最大限制为 32,767。所以使用 bigIntegers 更安全

以上是关于为啥在区域表定义中未创建 state_id 字段?的主要内容,如果未能解决你的问题,请参考以下文章

为啥声明类型时可以在 redux 中未定义状态?

为啥此 setInterval 中未定义此 useRef 值?

为啥我的变量在 useEffect 中定义的其他地方在反应中未定义?

为啥在使用 Promise 时在类方法中未定义“this”? [复制]

为啥在第一次组件渲染中未定义 useState 对象值?

为啥 this.$refs 在 Vue 子组件中未定义?