16
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

DjangoのQuerySet.delete が発行するクエリ

Last updated at Posted at 2014-11-06

Djangoの QuerySet.delete() を実行した時に実際に、発行されるクエリがちょっと想定と違ったので、メモ。Django1.7、データベースはMySQLで確認しています。

準備

  • 以下のようなmodels.pyを用意。
books/models.py
from django.db import models


class Author(models.Model):
    name = models.CharField(max_length=100)


class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.ForeignKey(Author)

  • テストデータを用意。
>>> from books.models import *
>>> a1 = Author.objects.create(name='Alice')
>>> a2 = Author.objects.create(name='Bob')
>>> Book.objects.create(title='book1', author=a1)
>>> Book.objects.create(title='book2', author=a1)
>>> Book.objects.create(title='comic1', author=a2)
>>> Book.objects.create(title='comic2', author=a2)

実験

QuerySet.delete() をいろいろな条件で実行してみた。

  • 単にfieldで絞り込む場合
>>> Book.objects.filter(title='comic1').delete()

DELETE FROM `books_book` WHERE `books_book`.`title` = 'comic1';

素直にDELETE FROM テーブル WHERE 条件 だった。

  • 外部テーブルを参照する場合
>>> Book.objects.filter(author__name='Bob').delete()


SELECT `books_book`.`id` FROM `books_book` INNER JOIN `books_author` ON ( `books_book`.`author_id` = `books_author`.`id` ) WHERE `books_author`.`name` = 'Bob';
DELETE FROM `books_book` WHERE `books_book`.`id` IN (11, 10);

SELECT id FROM テーブル INNER JOIN ... WHERE 条件 してから
DELETE FROM テーブル WHERE id IN (...) していた。

  • 親テーブルをdeleteする場合
>>> Author.objects.all().delete()

SELECT `books_author`.`id`, `books_author`.`name` FROM `books_author`;
DELETE FROM `books_book` WHERE `books_book`.`author_id` IN (7, 8);
DELETE FROM `books_author` WHERE `books_author`.`id` IN (8, 7);

SELECT id FROM 親テーブル INNER JOIN ... WHERE 条件してから、子テーブルの関連するレコードをDELETEして、その後親テーブルのレコードをDELETE。
ここ曰く、

Django は、オブジェクトを削除する際に、通常 SQLでいう ON DELETE CASCADE 制約をエミュレートします。すなわち、 削除対象のオブジェクトを指すような外部キーを持つ全てのオブジェクトも 同時に削除されるのです。

とのこと。リンク先の例ではインスタンスのdeleteメソッドだけど、QuerySetでも同じような動作になるようだ。

まとめ

外部テーブル参照したり、親テーブルの場合、想定通りの動作か確認しておいたほうがいい。

deleteに限らず、ORM経由で操作するときはどんなクエリになるか確認しておいたほうが良さげ。

16
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?