如果索引存在于 Laravel 迁移中,如何检查它们?

Posted

技术标签:

【中文标题】如果索引存在于 Laravel 迁移中,如何检查它们?【英文标题】:How can indexes be checked if they exist in a Laravel migration? 【发布时间】:2018-02-03 14:20:57 【问题描述】:

在准备迁移时尝试检查表上是否存在唯一索引,如何实现?

Schema::table('persons', function (Blueprint $table) 
    if ($table->hasIndex('persons_body_unique')) 
        $table->dropUnique('persons_body_unique');
    
)

看起来像上面的东西。 (显然 hasIndex() 不存在)

【问题讨论】:

【参考方案1】:

使用 Laravel 使用的“doctrine-dbal”是更好的解决方案:

Schema::table('persons', function (Blueprint $table) 
    $sm = Schema::getConnection()->getDoctrineSchemaManager();
    $indexesFound = $sm->listTableIndexes('persons');

    if(array_key_exists("persons_body_unique", $indexesFound))
        $table->dropUnique("persons_body_unique");
);

【讨论】:

如上所述,这应该是正确的答案,因为它超越了 Laravel 的 Doctrine 并且不使用原生查询。 我可以确认这在 5.2 上有效,在我从 repo 安装了教义-dbal 包之后。 请注意listTableIndexes() 将返回小写的索引名称。 次要添加以在将来为其他迁移进行复制/粘贴,您可以使用 $table 对象来获取名称。 $indexesFound = $sm->listTableIndexes($table->getTable());【参考方案2】:

mysql 查询

SHOW INDEXES FROM persons

将返回表上的所有索引,但它包含除名称之外的其他信息。在我的设置中,包含名称的列称为Key_name,所以让我们获取键名的集合

collect(DB::select("SHOW INDEXES FROM persons"))->pluck('Key_name')

由于它是一个集合,您可以使用contains,所以我们终于有了:

if (collect(DB::select("SHOW INDEXES FROM persons"))->pluck('Key_name')->contains('persons_body_unique')) 
        $table->dropUnique('persons_body_unique');

【讨论】:

这不应该是公认的答案,因为它不是跨 dbms(“便携式”,不是特定于供应商的)。 @admirko 的答案要好得多,因为它跨越了 Laravel 的底层 Doctrine 层,而不是“本机查询”。【参考方案3】:

在简单的表单中,你可以这样做

Schema::table('persons', function (Blueprint $table) 
    $index_exists = collect(DB::select("SHOW INDEXES FROM persons"))->pluck('Key_name')->contains('persons_body_unique');
    if ($index_exists) 
        $table->dropUnique("persons_body_unique");
    
)

【讨论】:

以上是关于如果索引存在于 Laravel 迁移中,如何检查它们?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查文件是不是存在于laravel的url中

如何在 laravel 中运行特定迁移 [重复]

如果元素存在,则获取容器中元素的索引

如何检查记录是不是已经存在,然后在 laravel 中更新或插入?

Laravel 关于迁移的问题

Laravel 迁移 - Model::find($id) 返回 NULL 但 $id 存在于数据库中