2010-09-28 47 views
3

我在使用Sql Server和pyodbc的Django项目中运行South迁移。这是向后迁移,所以南方正试图删除我的一些表格。Sql Server中的DROP CASCADE

南以删除表执行下面的方法:

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的解决方案都是有效的。

回答

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

“模拟”DROP CASCADE是什么意思?

如果这意味着“忽略MSSQL的级联参数”,那么你可以检查当前正在使用的SQL平台/方言,并做任何你喜欢的事情(我不知道如何/如果这是可能的)。 sqlalchemy方言的实施可能会给你一些有用的想法,如果你需要它们。

但是如果你想真正实现的功能,你必须查询系统视图来建立表的列表删除并以正确的顺序将它们置于;对于INFORMATION_SCHEMA观点或sys.foreign_keys文件应帮帮我。一旦你有一个查询以正确的顺序获得依赖表,你可以修补函数来做实际的DROP。

+0

通过“模拟”我的意思是,我需要写代码,不正是一个DROP CASCADE会如果MSSQL有它实现的事情。 – 2010-09-28 13:41:43