如何迁移更改列类型?

时间:2017-03-08 04:33:39

标签: laravel laravel-5 laravel-5.4 dbal

我收到错误,当我尝试从字符串到文本的列类型时,使用Laravel的迁移功能。

文件:{data_time} _change_db_structure.php

public function up()
  {
    Schema::table('service_request_type', function (Blueprint $table) {
      $table->dropIndex(['sro_key_group']);

      $table->text('sro_key_group')->change();
      $table->renameColumn('sro_key_group', 'tags');
    });
  }

这是原始迁移创建表文件。

public function up()
  {
    Schema::create('service_request_type', function (Blueprint $table) {
      $table->engine = 'InnoDB';
      ...
      $table->string('sro_key_group', 100)->nullable()->index();
      ...
    });
  }

我得到了错误。

  

[照亮\数据库\ QueryException]
  SQLSTATE [42000]:语法错误或访问冲突:1170 BLOB / TEXT   专栏' sro_key_group'用于密钥规范而没有密钥长度   (SQL:ALTER TABLE service_request_type CHANGE sro_key_group sro _key_group TEXT DEFAULT NULL COLLATE utf8_unicode_ci)

                                                                                                                                          [Doctrine\DBAL\Driver\PDOException]                                   
     

SQLSTATE [42000]:语法错误或访问冲突:1170 BLOB / TEXT   专栏' sro_key_group'在没有密钥长度的密钥规范中使用

                                                                                                                                          [PDOException]                                                        
     

SQLSTATE [42000]:语法错误或访问冲突:1170 BLOB / TEXT   专栏' sro_key_group'在没有密钥长度的密钥规范中使用

有什么不对?我已经在doctrine/dbal安装了composer.json

2 个答案:

答案 0 :(得分:4)

您需要分三步执行此操作,或者使用三次单独的迁移,或者三次调用table(),如您在答案中所示。

第一个问题是,即使您按照您希望它们执行的顺序编写语句(以及它们需要执行的顺序),架构构建器实际上会重新排列顺序以便“更改”语句首先执行。模式构建器将新列和已更改的列视为“隐含”语句,并将它们移动到要运行的命令堆栈的顶部。但是,重命名语句不被视为“更改”语句。

所以,即使您已将代码写入:

[
    remove index,
    change column from varchar to text,
    rename column,
]

架构构建器实际上将执行:

[
    change column from varchar to text,
    remove index,
    rename column,
]

现在,由于在从索引中删除列之前发生了更改命令,因此您收到1170错误。

下一个问题是尝试在同一个上下文中进行列更改和列重命名。实现请求更改的SQL是通过执行模式差异生成的,但是两个模式差异都将在实际进行任何更改之前完成。因此,从varchartext的第一次更改将生成相应的SQL以进行更改,但是第二次更改以重命名该列将实际生成更改列的SQL 重命名文本字段。

要解决这些问题,您可以创建三个迁移,其中第一个迁移只是删除索引,第二个迁移更改类型,然后第三个迁移重命名它,或者您可以保留一个迁移并运行三个table()陈述。

public function up()
{
    // make sure the index is dropped first
    Schema::table('service_request_type', function (Blueprint $table) {
        $table->dropIndex(['sro_key_group']);
    });

    // now change the type of the field
    Schema::table('service_request_type', function (Blueprint $table) {
        $table->text('sro_key_group')->nullable()->change();
    });

    // now rename the field
    Schema::table('service_request_type', function (Blueprint $table) {
        $table->renameColumn('sro_key_group', 'tags');
    });
}

答案 1 :(得分:0)

Ahhhhhh mannnnn ......

我得到了答案。

public function up()
  {
    Schema::table('service_request_type', function (Blueprint $table) {
      $table->dropIndex(['sro_key_group']);
    });
    Schema::table('service_request_type', function (Blueprint $table) {
      $table->text('sro_key_group')->nullable()->change();
    });
    Schema::table('service_request_type', function (Blueprint $table) {
      $table->renameColumn('sro_key_group', 'tags');
    });
  }

嗯嗯WTF是那个?