2010-09-28 49 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