Operações em massa com mssql-django

Este artigo explica como usar os métodos bulk_create e bulk_update do Django com o SQL Server por meio do back-end mssql-django.

criação_em_massa

Use bulk_create para inserir vários registros em uma única operação de banco de dados:

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)

Retornar linhas de uma inserção em lote

Por padrão, bulk_create não retorna chaves primárias preenchidas ao usar SQL Server. Para habilitar o retorno de chaves primárias, defina return_rows_bulk_insertTrue em seu banco de dados 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,
        },
    },
}

Importante

Defina return_rows_bulk_insert como False (o padrão) se qualquer tabela de destino tiver gatilhos. A OUTPUT cláusula usada para retornar linhas não é compatível com tabelas que têm INSERT gatilhos.

atualização_em_massa

Use bulk_update para atualizar vários registros em uma única operação de banco de dados:

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"])

O parâmetro padrão

O mssql-django backend ainda aceita um parâmetro default em bulk_update para manter compatibilidade com versões anteriores, mas isso não afeta o SQL gerado nas versões atuais.

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

O backend agora processa todos os casos de atualização com NULL sem a necessidade de default.

Note

Em versões mais antigas, a omissão default pode disparar o erro de SQL Server mostrado no exemplo anterior. O parâmetro permanece aceito apenas para evitar a interrupção de sites de chamadas mais antigos.

Tamanho do lote

Para conjuntos de dados grandes, use o batch_size parâmetro para limitar o número de linhas por instrução 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)