mssql-django を使用した一括操作

この記事では、bulk_create バックエンドを介して Django のbulk_updateメソッドと mssql-django メソッドをSQL Serverと共に使用する方法について説明します。

一括作成

bulk_createを使用して、1 つのデータベース操作に複数のレコードを挿入します。

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)

一括挿入から行を返す

既定では、SQL Serverを使用する場合、bulk_createは設定された主キーを返しません。 主キーの返しを有効にするには、return_rows_bulk_insertをデータベース TrueOPTIONSに設定します。

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を使用して、1 つのデータベース操作で複数のレコードを更新します。

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 バックエンドは、下位互換性のためにdefaultbulk_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)