如何在Laravel迁移中检查索引是否存在?

37

如何在准备迁移时检查表中是否存在唯一索引?

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

类似上述内容的东西。(显然,hasIndex()方法不存在)

3个回答

86

使用 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 并且不使用本地查询。 - Roland
1
我可以确认,在我从仓库安装了doctrine-dbal包之后,它可以在5.2上运行。 - Filip Filipovic
5
请注意,listTableIndexes() 方法返回的索引名称是 小写字母 - RyanNerd
9
为了方便今后的迁移工作,您可以在代码中添加一行来使用 $table 对象获取表名。该行代码如下:$indexesFound = $sm->listTableIndexes($table->getTable()); - JKOlaf

14

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

2
这不应该是被接受的答案,因为它不是跨数据库管理系统(“可移植”,而不是特定于供应商)。@admirko的答案要好得多,因为它涉及Laravel的基础Doctrine层,而不是“本地查询”。 - Roland

4
在简单表单中,您可以这样做。
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");
    }
})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接