Operações em massa com mssql-django

Este artigo explica como utilizar os métodos bulk_create e bulk_update do Django com o SQL Server através do backend mssql-django.

criar_em_massa

Use bulk_create para inserir múltiplos registos numa única operação de base 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)

Devolver linhas de uma inserção em massa

Por defeito, bulk_create não devolve as chaves primárias preenchidas ao usar o SQL Server. Para permitir a devolução de chaves primárias, defina return_rows_bulk_insert para True na sua base 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 (a predefinição) se alguma tabela de destino tiver acionadores. A OUTPUT cláusula usada para devolver linhas não é compatível com tabelas que tenham INSERT triggers.

bulk_update

Use bulk_update para atualizar múltiplos registos numa única operação de base 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 back-end ainda aceita um parâmetro default no bulk_update por retrocompatibilidade, mas este 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 gere todosNULL os casos de atualização sem exigir default.

Note

Em versões mais antigas, omitir default podia desencadear o erro do SQL Server mostrado no exemplo anterior. O parâmetro permanece aceite apenas para evitar quebrar os 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)