【问题标题】:How I can drop an index if exist using django migrations.RunSQL and MySQL如果存在使用 django migrations.RunSQL 和 MySQL,我如何删除索引
【发布时间】:2017-09-25 07:26:04
【问题描述】:

我正在尝试使用 migrations.RunSQL 删除索引,但我遇到了不存在的问题,有没有办法仅在存在的情况下删除索引?类似于 migrations.RunSQL("DROP INDEX IF EXISTS index_id ON table")。

  1. Django 1.8.18
  2. MySQL 5.6

非常感谢

【问题讨论】:

标签: mysql django django-migrations


【解决方案1】:

由于 MySQL 不支持 IF EXISTS 索引,您可能需要编写自己的迁移:

def drop_index_if_exists(apps, schema_editor):
    # access to the connection since schema_editor.execute does not return the cursor
    with schema_editor.connection.cursor() as cursor:
       cursor.execute("SHOW INDEX FROM table_name WHERE KEY_NAME = 'index_name'");
       exists = int(cursor.fetchone()) > 0
    # outside with to close the cursor
    if exists:
        schema_editor.execute("CREATE INDEX index_name ON ...")

operations = [
    migrations.RunPython(drop_index_if_exists)
]

为了一致性,您可以编写一个create_index_if_not_exists 方法来取消应用迁移,并调用它:

migrations.RunPython(drop_index_if_exists, create_index_if_not_exists)

【讨论】:

  • 非常感谢你,我已经用你的想法解决了:D
  • exists = True if cursor.fetchone() else False 将永远是True。您必须检查值
  • 我已经测试过,如果查询不返回行,则 cursor.fetchone() 将返回 None:In [1]: from django.db import connectionIn [2]: with connection.cursor() as cursor:cursor.execute("SHOW INDEX FROM table1 WHERE KEY_NAME = 'index_name'")cursor.execute("SHOW INDEX FROM table1 WHERE KEY_NAME = 'index_name'")print cursor.fetchone()(u'table1', 1L, u'index_name', 1L, u'index_name')In [3]: with connection.cursor() as cursor:@ 987654333@print cursor.fetchone()None
【解决方案2】:

这里有一个解决方案,谢谢@alfonso.kim 的想法

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations


def drop_index_if_exists_and_create(apps, schema_editor):
    # access to the connection since schema_editor.execute does not return the cursor
    with schema_editor.connection.cursor() as cursor:
        cursor.execute("SHOW INDEX FROM table_name WHERE KEY_NAME = 'index_name'")
        exists = True if cursor.fetchone() else False
    # outside with to close the cursor
    if exists:
        schema_editor.execute("DROP INDEX index_name ON table_name")

    schema_editor.execute("CREATE INDEX index_name ON table_name(index_name(191))")


class Migration(migrations.Migration):

    dependencies = [
        ('table_name', ''),
    ]

    operations = [
        migrations.RunPython(drop_index_if_exists_and_create)
    ]

【讨论】:

    【解决方案3】:

    执行您的代码后,我遇到了事务错误:

    django.db.transaction.TransactionManagementError: Executing DDL statements while in a transaction on databases that can't perform a rollback is prohibited.
    

    Django 2.5 MySql 5.7

    【讨论】:

      猜你喜欢
      • 2011-01-29
      • 2011-02-12
      • 2010-12-31
      • 2013-11-16
      • 2020-12-28
      • 1970-01-01
      • 2018-08-29
      • 2020-01-23
      相关资源
      最近更新 更多