我正在使用Sql Server和pyodbc的Django项目中运行South迁移。这是向后迁移,所以南方试图删除我的一些表。
南方执行以下方法以删除表格:
def delete_table(self, table_name, cascade=True):
"""
Deletes the table 'table_name'.
"""
params = (self.quote_name(table_name), )
if cascade:
self.execute('DROP TABLE %s CASCADE;' % params)
else:
self.execute('DROP TABLE %s;' % params)
drop_table = alias('delete_table')
问题是Sql Server不支持级联丢弃,因此迁移失败并出现以下错误:
pyodbc.ProgrammingError: ('42000', "[42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Incorrect syntax near the keyword 'CASCADE'. (156) (SQLExecDirectW)")
我想写一个南方的补丁,以便它可以与Sql Server一起使用。什么是模拟DROP CASCADE的最佳方法?我认为使用python或纯SQL的两种解决方案都是有效的。
答案 0 :(得分:2)
我从来没有在python中找到DROP CASCADE的实现,所以我最终编写了自己的。以下是它的外观:
def delete_table(self, table_name, cascade=True):
"""
Deletes the table 'table_name'.
"""
params = (self.quote_name(table_name), )
if cascade:
conn = self._get_connection()
# Get a list of related tables
sql = "SELECT T1.TABLE_NAME \
FROM INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE AS T1 \
JOIN SYS.FOREIGN_KEYS AS F \
ON (F.parent_object_id = OBJECT_ID(N'{0}') OR \
F.referenced_object_id = OBJECT_ID(N'{0}')) AND \
T1.CONSTRAINT_NAME = OBJECT_NAME(F.object_id)"
related_tables = self.execute(sql.format(params[0]))
# Drop all the constraints
constraints = self.execute("SELECT CONSTRAINT_NAME \
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS \
WHERE TABLE_NAME='{0}' AND \
CONSTRAINT_TYPE='FOREIGN KEY';".format(table_name))
sql = "ALTER TABLE {0} DROP CONSTRAINT {1};"
for constraint in constraints:
self.execute(sql.format(params[0], constraint[0]))
for table in related_tables:
self.delete_table(table[0], cascade)
sql = "IF EXISTS (SELECT * \
FROM sys.objects \
WHERE object_id = OBJECT_ID(N'{0}') AND \
type in (N'U')) \
DROP TABLE {0}"
self.execute(sql.format(params[0]))
else:
self.execute('DROP TABLE %s;' % params)
答案 1 :(得分:1)
“模拟”DROP CASCADE是什么意思?
如果它意味着“忽略MSSQL的cascade参数”,那么你可以检查当前正在使用的SQL平台/方言并做任何你喜欢的事情(我不知道如何/如果可能)。如果需要,sqlalchemy方言的实现可能会给你一些有用的想法。
但是,如果您想要实际实现该功能,您将查询系统视图以构建要删除的表列表以及删除它们的正确顺序.INFORMATION_SCHEMA视图或sys.foreign_keys的文档应该有帮助。一旦有了查询以正确的顺序获取依赖表,就可以修补函数来执行实际的DROP。