【发布时间】:2017-09-25 07:26:04
【问题描述】:
我正在尝试使用 migrations.RunSQL 删除索引,但我遇到了不存在的问题,有没有办法仅在存在的情况下删除索引?类似于 migrations.RunSQL("DROP INDEX IF EXISTS index_id ON table")。
- Django 1.8.18
- MySQL 5.6
非常感谢
【问题讨论】:
标签: mysql django django-migrations
我正在尝试使用 migrations.RunSQL 删除索引,但我遇到了不存在的问题,有没有办法仅在存在的情况下删除索引?类似于 migrations.RunSQL("DROP INDEX IF EXISTS index_id ON table")。
非常感谢
【问题讨论】:
标签: mysql django django-migrations
由于 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)
【讨论】:
exists = True if cursor.fetchone() else False 将永远是True。您必须检查值
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
这里有一个解决方案,谢谢@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)
]
【讨论】:
执行您的代码后,我遇到了事务错误:
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
【讨论】: