2013-03-07 62 views
3

我需要能夠快速批量插入大量記錄,同時仍能確保數據庫中的唯一性。要插入的新記錄已被解析,並且是唯一的。我希望有一種方法可以在數據庫級別執行唯一性,而不是在代碼本身。Django獨特的批量插入

我正在使用MySQL作爲數據庫後端。如果django支持任何其他數據庫中的此功能,我可以靈活地更改後端,因爲這是一項要求。

在Django中的批量插入不使用save方法,那麼我怎樣才能一次插入幾百到幾千條記錄,同時仍然尊重唯一字段和唯一字段?


我的模型結構,簡化的,是這個樣子:

class Example(models.Model): 
    Meta: 
     unique_together = (('name', 'number'),) 

    name = models.CharField(max_length = 50) 
    number = models.CharField(max_length = 10) 
    ... 
    fk = models.ForeignKey(OtherModel) 

編輯:

已經不在數據庫中的記錄應該被插入,並且記錄已經存在的應該被忽略。

+0

您原始數據的格式是?如果它是一個csv,我想知道你是否可以循環遍歷每個條目並以這種方式保存。 – djq 2013-03-07 04:09:03

+0

['get_or_create'](https://docs.djangoproject.com/en/1.6/ref/models/querysets/#get-or-create)。 – 2014-01-11 05:42:33

回答

0

Django本身不強制執行unique_together元屬性。這由數據庫使用UNIQUE子句實施。您可以根據需要插入儘可能多的數據,並保證指定的字段是唯一的。如果不是,那麼將會引發異常(不確定哪一個)。更多關於docsunique_together

1

正如miki725所提到的,您對當前的代碼沒有問題。 我假設你正在使用bulk_create方法。 save()方法在使用bulk_create時未被調用,但字段的唯一性在save()方法內未被強制執行。

Django的:

unique_together = (('name', 'number'),) 

的MySQL:

UNIQUE KEY `name` (`name`,`number`) 

所以,如果你插入值當您使用unique_together一個唯一約束創建表時被添加到基礎表在MySQL使用任何方法(save,bulk_insert或者甚至是原始的sql)將數據導入表中,您將從mysql獲得此異常:

Duplicate entry 'value1-value2' for key 'name' 

UPDATE:

做什麼bulk_insert是,它創建了一次插入所有數據與一個查詢一個大的查詢。所以如果其中一個條目是重複的,它會拋出一個異常,並且沒有插入任何數據。

1-一種選擇是使用bulk_insert的batch_size參數,並使其在多個批次中插入數據,以便在其中一個失敗時只丟失該批次的其餘數據。 (取決於插入所有數據的重要性以及重複條目的頻率)

2-另一種選擇是在批量數據上編寫一個for循環並逐個插入批量數據。通過這種方式,僅爲該行引發異常,並插入其餘數據。這是每次都要查詢數據庫,當然慢很多。

3-第三個選項是取消唯一約束,使用bulk_create插入數據,然後編寫一個刪除重複行的簡單查詢。

+0

這是否仍然插入其餘記錄? – NickCSE 2013-03-07 14:45:01

+0

@NickCSE plz查看答案更新 – jurgenreza 2013-03-07 16:01:56

+0

不幸的是,我不能錯過任何數據,每條記錄都必須使它進入數據庫。我目前正在做類似#2的事情,而且速度很慢,導致我問這個問題。我想到了#3,但這似乎根本沒有可擴展性。每個批量插入可以是成千上萬條記錄中的10個。 – NickCSE 2013-03-07 19:56:48