【问题标题】:Laravel Migration Change to Make a Column NullableLaravel 迁移更改以使列可为空
【发布时间】:2014-08-16 16:26:43
【问题描述】:

我使用未签名的user_id 创建了一个迁移。如何在新迁移中编辑 user_id 以使其也成为 nullable()

Schema::create('throttle', function(Blueprint $table)
{
    $table->increments('id');
    // this needs to also be nullable, how should the next migration be?
    $table->integer('user_id')->unsigned();
}

【问题讨论】:

    标签: laravel laravel-5 eloquent nullable laravel-migrations


    【解决方案1】:

    我不得不使用nullable(true)

    Schema::table('users', function($table)
    {
        $table->string('name', 50)->nullable(true)->change();
    });
    

    【讨论】:

      【解决方案2】:

      添加到Dmitri Chebotarevanswer,对于 Laravel 5+。

      在需要 doctrine/dbal 包之后:

      composer require doctrine/dbal
      

      然后您可以使用可为空的列进行迁移,如下所示:

      public function up()
      {
          Schema::table('users', function (Blueprint $table) {
              // change() tells the Schema builder that we are altering a table
              $table->integer('user_id')->unsigned()->nullable()->change();
          });
      }
      

      要恢复操作,请执行以下操作:

      public function down()
      {
          /* turn off foreign key checks for a moment */
          DB::statement('SET FOREIGN_KEY_CHECKS = 0');
          /* set null values to 0 first */
          DB::statement('UPDATE `users` SET `user_id` = 0 WHERE `user_id` IS NULL;');
          /* alter table */
          DB::statement('ALTER TABLE `users` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
          /* finally turn foreign key checks back on */
          DB::statement('SET FOREIGN_KEY_CHECKS = 1');
      }
      

      【讨论】:

        【解决方案3】:

        请注意,这仅适用于 Laravel 5+。

        首先你需要 doctrine/dbal 包:

        composer require doctrine/dbal
        

        现在在您的迁移中,您可以执行此操作以使该列可以为空:

        public function up()
        {
            Schema::table('users', function (Blueprint $table) {
                // change() tells the Schema builder that we are altering a table
                $table->integer('user_id')->unsigned()->nullable()->change();
            });
        }
        

        您可能想知道如何恢复此操作。遗憾的是,不支持这种语法:

        // Sadly does not work :'(
        $table->integer('user_id')->unsigned()->change();
        

        这是恢复迁移的正确语法:

        $table->integer('user_id')->unsigned()->nullable(false)->change();
        

        或者,如果您愿意,可以编写原始查询:

        public function down()
        {
            /* Make user_id un-nullable */
            DB::statement('UPDATE `users` SET `user_id` = 0 WHERE `user_id` IS NULL;');
            DB::statement('ALTER TABLE `users` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
        }
        

        【讨论】:

        • 这是 L5 最完整的答案,但应该提到的是,如果 'user_id' 是外键,它应该是,除非你运行',否则你将无法更改它DB::statement('SET FOREIGN_KEY_CHECKS = 0');'第一的。完成后将其设置回 1。
        • 谢谢,nullable(false) 救了我,因为nullable() 没有很好的文档记录,也没有notNull() 功能。
        • 这不适用于带有 postgres 的外键。尝试SET FOREIGN_KEY_CHECKS = 0 会出错。您可能需要使用原始查询来更改表的约束。看这里:postgresql.org/docs/current/static/sql-altertable.html
        • 这打破了我的测试。测试开始运行,然后挂起。我想第一次回滚会导致这种情况。导致 MySQL 和 SQLite 的测试挂起。
        【解决方案4】:

        安装 Composer 包:

        composer require doctrine/dbal
        

        成功安装 composer 包后,我们可以使用迁移命令更改数据类型和更改列名。

        语法:

        php artisan make:migration alter_table_[table_name]_change_[column_name] --table=[table_name]
        

        例子:

        php artisan make:migration alter_table_sessions_change_user_id --table=sessions
        
        <?php
        
        use Illuminate\Database\Migrations\Migration;
        use Illuminate\Database\Schema\Blueprint;
        use Illuminate\Support\Facades\Schema;
        
        class AlterTableSessionsChangeUserId extends Migration
        {
            /**
             * Run the migrations.
             *
             * @return void
             */
            public function up()
            {
                Schema::table('sessions', function (Blueprint $table) {
                    $table->integer('user_id')->unsigned()->nullable()->change();
                });
            }
        
            /**
             * Reverse the migrations.
             *
             * @return void
             */
            public function down()
            {
                Schema::table('sessions', function (Blueprint $table) {
                    $table->dropColumn('user_id');
                });
            }
        }
        

        然后运行:php artisan migrate

        或刷新表以更改列名。不要使用change 方法。

        Schema::create('throttle', function(Blueprint $table)
        {
            $table->increments('id');
            # old code
            $table->integer('user_id')->unsigned();
            # new code
            $table->integer('user_id')->unsigned()->nullable();
        }
        

        注意:下面的命令用于清除表中的数据。

        php artisan migrate:refresh --path=/database/migrations/2021_09_31_050851_create_throttle_table.php
        

        【讨论】:

          【解决方案5】:

          Laravel 5 现在支持更改列;这是官方文档中的一个示例:

          Schema::table('users', function($table)
          {
              $table->string('name', 50)->nullable()->change();
          });
          

          来源:http://laravel.com/docs/5.0/schema#changing-columns

          Laravel 4 不支持修改列,因此您需要使用另一种技术,例如编写原始 SQL 命令。例如:

          // getting Laravel App Instance
          $app = app();
          
          // getting laravel main version
          $laravelVer = explode('.',$app::VERSION);
          
          switch ($laravelVer[0]) {
          
              // Laravel 4
              case('4'):
          
                  DB::statement('ALTER TABLE `pro_categories_langs` MODIFY `name` VARCHAR(100) NULL;');
                  break;
          
              // Laravel 5, or Laravel 6
              default:                
          
                  Schema::table('pro_categories_langs', function(Blueprint $t) {
                      $t->string('name', 100)->nullable()->change();
                  });               
          
          }
          

          【讨论】:

          • 谢谢。但是我怎样才能做到相反呢?如何将列更改为不可为空?有什么想法吗?
          • @algorhythm 你试试这个' $t->string('name', 100)->change();'
          • 你需要需要学说\dbal 才能迁移
          • @algorhythm -&gt;nullable(false) 将让您再次更改该列。
          • ->change() 要求您安装 Doctrine DBAL 包,并且它本身并不能识别 laravel 开箱即用的所有相同列类型。例如 double 不是识别到 DBAL 的列类型。
          【解决方案6】:

          对于 Laravel 4.2,Unnawut 上面的答案是最好的答案。但是如果你使用的是表前缀,那么你需要稍微修改一下你的代码。

          function up()
          {
              $table_prefix = DB::getTablePrefix();
              DB::statement('ALTER TABLE `' . $table_prefix . 'throttle` MODIFY `user_id` INTEGER UNSIGNED NULL;');
          }
          

          为了确保您仍然可以回滚迁移,我们还将执行down()

          function down()
          {
              $table_prefix = DB::getTablePrefix();
              DB::statement('ALTER TABLE `' . $table_prefix . 'throttle` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
          }
          

          【讨论】:

            【解决方案7】:

            他是 Laravel 5 的完整迁移者:

            public function up()
            {
                Schema::table('users', function (Blueprint $table) {
                    $table->unsignedInteger('user_id')->nullable()->change();
                });
            }
            
            public function down()
            {
                Schema::table('users', function (Blueprint $table) {
                    $table->unsignedInteger('user_id')->nullable(false)->change();
                });
            }
            

            关键是,您可以通过将false 作为参数传递来删除nullable

            【讨论】:

              【解决方案8】:

              添加到 Dmitri Chebotarev 答案,

              如果你想一次改变多个列,你可以像下面那样做

              DB::statement('
                   ALTER TABLE `events` 
                          MODIFY `event_date` DATE NOT NULL,
                          MODIFY `event_start_time` TIME NOT NULL,
                          MODIFY `event_end_time` TIME NOT NULL;
              ');
              

              【讨论】:

                【解决方案9】:

                我假设您正在尝试编辑已添加数据的列,因此在不丢失数据的情况下删除列并再次添加为可空列是不可能的。我们将 alter 现有列。

                但是,Laravel 的架构构建器不支持修改列,除了重命名列。 因此,您将需要运行原始查询来执行它们,如下所示:

                function up()
                {
                    DB::statement('ALTER TABLE `throttle` MODIFY `user_id` INTEGER UNSIGNED NULL;');
                }
                

                为了确保您仍然可以回滚迁移,我们还将执行 down()

                function down()
                {
                    DB::statement('ALTER TABLE `throttle` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
                }
                

                请注意,由于您在可空和不可空之间进行转换,因此您需要确保在迁移之前/之后清理数据。所以在你的迁移脚本中这样做:

                function up()
                {
                    DB::statement('ALTER TABLE `throttle` MODIFY `user_id` INTEGER UNSIGNED NULL;');
                    DB::statement('UPDATE `throttle` SET `user_id` = NULL WHERE `user_id` = 0;');
                }
                
                function down()
                {
                    DB::statement('UPDATE `throttle` SET `user_id` = 0 WHERE `user_id` IS NULL;');
                    DB::statement('ALTER TABLE `throttle` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
                }
                

                【讨论】:

                • 对于 Laravel 4,将 query 替换为 statement
                • 谢谢@Razor。相应地更新了我的答案。
                • 在第二个代码块的down函数中,SQL语句应该以NOT NULL结尾。 (第三个例子中的down函数是正确的。)
                【解决方案10】:

                如果您碰巧更改了列并偶然发现

                'Doctrine\DBAL\Driver\PDOMySql\Driver' not found
                

                然后安装

                composer require doctrine/dbal

                【讨论】:

                【解决方案11】:

                试试看:

                $table->integer('user_id')->unsigned()->nullable();
                

                【讨论】:

                • 它不会改变现有的列
                • 你最后忘了-&gt;change,只提Laravel 5+
                • 你需要composer require doctrine/dbal
                猜你喜欢
                • 2023-03-19
                • 2012-12-10
                • 2016-01-07
                • 2020-11-11
                • 2012-11-02
                • 2011-08-23
                • 2019-05-29
                • 2013-09-10
                • 2021-03-20
                相关资源
                最近更新 更多