使用 mssql-django 进行批量操作

本文介绍如何通过mssql-django后端将 Django 的bulk_createbulk_update方法与 SQL Server 一起使用。

批量创建

用于 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时不会返回填充的主键。 若要启用返回主键,请在数据库OPTIONS中将return_rows_bulk_insert设置为True

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_insertFalse (默认值)。 用于返回行数据的 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 后端出于向后兼容考虑,仍会在 bulk_update 上接受 default 参数,但在当前版本中,它不会影响生成的 SQL。

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

后端现在可以处理所有 all-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)