【问题标题】:How to migration change columns type?如何迁移更改列类型?
【发布时间】:2017-07-28 12:49:27
【问题描述】:

我得到一个错误,当我尝试从字符串到文本的列类型时,使用 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();
      ...
    });
  }

我遇到了错误。

[照亮\数据库\查询异常]
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”

怎么了?我已经在我的composer.json 中安装了doctrine/dbal

【问题讨论】:

  • sro_key_group 是否在多个索引中?
  • @patricus sro_key_group 不是多个索引
  • @ThunderBirdsX3 看到这个stackoverflow.com/questions/1827063/…
  • @GauravDave 谢谢,但请看下面我的回答。
  • 是的,我看到了。我分享的链接和你写的答案不匹配(不知何故)。

标签: laravel laravel-5 laravel-5.4 dbal


【解决方案1】:

您需要分三个步骤执行此操作,或者使用三个单独的迁移,或者对 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 来进行该更改,但是重命名列的第二次更改实际上会生成将列 back 更改为重命名文本字段。

要解决这些问题,您可以创建三个迁移,其中第一个迁移只是删除索引,第二个迁移更改类型,然后第三个迁移重命名它,或者您可以保留一个迁移并运行三个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');
    });
}

【讨论】:

  • 哇太棒了!!非常感谢。
  • 嗯,您的回答中似乎sro_key_group 没有更改为text,但在我的回答中它有效。
  • @ThunderBirdsX3 我已经更新了我的答案,提供了更多关于为什么会发生这种情况的信息。
【解决方案2】:

啊啊啊啊啊……

我得到了答案。

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');
    });
  }

嗯嗯嗯嗯嗯嗯嗯嗯嗯嗯是吗?

【讨论】:

  • 我知道发生了什么事。我会写一个答案。
  • 我发布了一个答案,让您知道您遇到问题的原因。
猜你喜欢
  • 1970-01-01
  • 2021-12-04
  • 2016-02-29
  • 2015-02-07
  • 2020-10-21
  • 1970-01-01
  • 1970-01-01
  • 2013-01-28
  • 1970-01-01
相关资源
最近更新 更多