Массовые операции с mssql-django

В этой статье объясняется, как использовать методы Django bulk_create и bulk_update с SQL Server через бэкенд mssql-django.

массовое создание

Используется bulk_create для вставки нескольких записей в одну операцию базы данных:

from myapp.models import Product

products = [
    Product(name="Widget A", price=9.99),
    Product(name="Widget B", price=14.99),
    Product(name="Widget C", price=19.99),
]

Product.objects.bulk_create(products)

Возврат строк из массовой вставки

По умолчанию bulk_create не возвращает заполненные первичные ключи при использовании SQL Server. Чтобы включить возврат первичных ключей, задайте значение return_rows_bulk_insertTrue в базе данных OPTIONS:

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "USER": "<your-username>",
        "PASSWORD": "<your-password>",
        "HOST": "<your-server>",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "return_rows_bulk_insert": True,
        },
    },
}

Important

return_rows_bulk_insert Установите значение False (по умолчанию), если какая-либо целевая таблица имеет триггеры. Конструкция OUTPUT, используемая для возврата строк, несовместима с таблицами с INSERT-триггерами.

массовое обновление

Используется bulk_update для обновления нескольких записей в одной операции базы данных:

from decimal import Decimal

from myapp.models import Product

products = Product.objects.filter(category="widgets")
for product in products:
    product.price = product.price * Decimal("1.10")  # 10% price increase

Product.objects.bulk_update(products, ["price"])

Параметр по умолчанию

mssql-django серверная часть по-прежнему принимает параметр default в bulk_update для обратной совместимости, но в текущих версиях этот параметр не влияет на генерируемый SQL.

At least one of the result expressions in a CASE specification must be an expression other than the NULL constant.

Серверная часть теперь обрабатывает все случаиNULL обновления без необходимости в default.

Note

В более ранних версиях опущение default может вызвать ошибку SQL Server, показанную в предыдущем примере. Параметр по-прежнему поддерживается только для того, чтобы не нарушить работу старых мест вызова.

Размер партии

Для больших наборов данных используйте batch_size параметр, чтобы ограничить количество строк на инструкцию SQL:

from myapp.models import Product

new_products = [Product(name=f"Widget {i}") for i in range(2000)]
Product.objects.bulk_create(new_products, batch_size=500)

products = list(Product.objects.filter(name__startswith="Widget "))
Product.objects.bulk_update(products, ["price"], batch_size=500)