Migrar aplicativos Django de outros bancos de dados para SQL Server

Este artigo fornece diretrizes para migrar aplicativos Django do PostgreSQL, MySQL ou SQLite para SQL Server usando o mssql-django back-end.

Overview

O ORM do Django abstrai a maioria das diferenças de banco de dados, mas alguns comportamentos e dialetos SQL variam entre back-ends. Este guia aborda as principais diferenças encontradas ao migrar para SQL Server.

Etapa 1: Instalar mssql-django

Instale o mssql-django pacote e suas dependências:

pip install mssql-django

Verifique se o Microsoft Driver ODBC para SQL Server está instalado. Consulte Instalar mssql-django para obter instruções específicas da plataforma.

Etapa 2: atualizar DATABASE a configuração

Substitua sua configuração de banco de dados existente em settings.py:

# Example: From PostgreSQL
# DATABASES = {
#     "default": {
#         "ENGINE": "django.db.backends.postgresql",
#         "NAME": "mydb",
#     },
# }

# To SQL Server
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",
        },
    },
}

Etapa 3: Criar novas migrações

Comece com um histórico de migração limpo para SQL Server:

# Remove existing migration files (keep __init__.py)
# Then regenerate
python manage.py makemigrations
python manage.py migrate

Importante

Transfira seus dados usando uma migração de dados ou um processo ETL separado. Não tente executar arquivos de migração do PostgreSQL ou MySQL em SQL Server.

Principais diferenças do PostgreSQL

Característica PostgreSQL SQL Server (mssql-django)
Incremento automático SERIAL / BIGSERIAL IDENTITY(1,1)
Tipo booliano Nativo boolean bit (0 ou 1)
Campos de texto text (ilimitado) nvarchar(max)
Suporte a JSON Nativo jsonb nvarchar(max) com funções JSON (SQL Server 2016+)
Campos de array ArrayField Sem suporte. Use uma tabela ou JSON relacionada.
Campos HStore HStoreField Sem suporte. Use JSONField em seu lugar.
Campos de intervalo IntegerRangeField, BigIntegerRangeField, , DateRangeFieldDateTimeRangeField Sem suporte. Use dois campos separados.
Pesquisa de texto completo SearchVector, SearchRank Use SQL bruto com a pesquisa de texto completo do SQL Server.
DISTINCT ON Suportado Sem suporte. Usar GROUP BY ou subconsultas.
DateTimeField com fuso horário timestamp with time zone datetimeoffset (quando USE_TZ=True) ou datetime2

Recursos específicos do PostgreSQL a serem substituídos

Se o seu código usa recursos específicos do PostgreSQL de django.contrib.postgres, substitua-os:

# PostgreSQL ArrayField - replace with JSONField or related table
# Before
from django.contrib.postgres.fields import ArrayField
tags = ArrayField(models.CharField(max_length=50))

# After (using JSONField)
tags = models.JSONField(default=list)

# PostgreSQL HStoreField - replace with JSONField
# Before
from django.contrib.postgres.fields import HStoreField
metadata = HStoreField()

# After
metadata = models.JSONField(default=dict)

Principais diferenças do MySQL

Característica MySQL SQL Server (mssql-django)
Incremento automático AUTO_INCREMENT IDENTITY(1,1)
Tipo booliano tinyint(1) bit
Campos de texto longtext nvarchar(max)
Suporte a JSON Nativo JSON (5.7 e posteriores) nvarchar(max) com funções JSON
Collation Configurável por coluna Nível de instância ou de banco de dados (sobrescrever com a opção COLLATE)
DateTimeField datetime(6) datetimeoffset ou datetime2

Principais diferenças do SQLite

Característica SQLite SQL Server (mssql-django)
Imposição de tipo Digitação flexível Imposição de tipo estrito
Gravações simultâneas Limited Suporte completo à concorrência
Número máximo de conexões Na prática, 1 gravador Agrupamento de conexões com muitas conexões simultâneas
DateTimeField Armazenado como texto datetimeoffset ou datetime2

Diferenças de ordenação

O agrupamento controla como o SQL Server compara e ordena o texto. Essa é uma das fontes mais comuns de comportamento inesperado ao migrar do PostgreSQL ou do MySQL.

Diferenciar maiúsculas de minúsculas

A ordenação padrão de SQL Server (SQL_Latin1_General_CP1_CI_AS) não diferencia maiúsculas de minúsculas. O PostgreSQL diferencia maiúsculas de minúsculas por padrão.

Esse comportamento significa que, após a migração, consultas que antes distinguiam entre "Smith" e "smith" passam a tratá-los como iguais:

# On PostgreSQL: returns only exact case matches
# On SQL Server (default collation): returns both "Smith" and "smith"
User.objects.filter(last_name="Smith")

Se o aplicativo depender de comparações que diferenciam maiúsculas de minúsculas, você terá duas opções:

  • Altere o agrupamento do banco de dados ou da coluna para uma variante com distinção entre maiúsculas e minúsculas:

    -- Database-level (affects all new columns)
    ALTER DATABASE [<your-database>] COLLATE Latin1_General_CS_AS;
    
    -- Column-level (for specific columns)
    ALTER TABLE [<your-table>]
    ALTER COLUMN [<column-name>] NVARCHAR (150) COLLATE Latin1_General_CS_AS;
    
  • Use a pesquisa do __exact Django com uma substituição de ordenação no SQL bruto para consultas direcionadas.

Sensibilidade a acentos

A agrupação padrão do SQL Server é sensível a acentos (AS), o que corresponde ao comportamento do PostgreSQL. Caracteres como é e e são tratados como diferentes. Se você precisar de comparações que não diferenciam ênfase, use uma ordenação que termina em _AI.

Configurar ordenação no mssql-django

Substitua a ordenação padrão para pesquisas de campo de texto na configuração do banco de dados:

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "collation": "Latin1_General_CS_AS",  # Case-sensitive
        },
    },
}

Note

A opção collation em mssql-django controla a ordenação usada em LIKE e nas operações de comparação geradas pelas consultas do ORM do Django. Ele não altera a ordenação de colunas existentes no banco de dados. Para alterar o agrupamento de uma coluna armazenada, use as instruções ALTER TABLE / ALTER COLUMN. Para obter mais informações, consulte documentação de agrupamento do SQL Server.

Etapa 4: Atualizar o SQL personalizado

Se o código contiver SQL bruto, atualize-o para SQL Server sintaxe:

# PostgreSQL syntax
# cursor.execute("SELECT * FROM products LIMIT 10 OFFSET 20")

# SQL Server syntax
cursor.execute("SELECT * FROM products ORDER BY id OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY")

Diferenças comuns de sintaxe SQL:

Operation PostgreSQL/MySQL SQL Server
Limitar resultados LIMIT 10 TOP 10 ou OFFSET ... FETCH NEXT ...
Concatenação de cadeia de caracteres \|\| (PG) / CONCAT() + ou CONCAT()
Literais booleanos TRUE / FALSE 1 / 0
Data/hora atual NOW() GETDATE(), SYSDATETIME()ou SYSDATETIMEOFFSET() para valores com reconhecimento de fuso horário
SE NÃO EXISTE CREATE TABLE IF NOT EXISTS Verificar sys.objects ou usar IF NOT EXISTS

Diferenças de isolamento de transação

O PostgreSQL usa MVCC (controle de concorrência multiversão) para o seu nível de isolamento READ COMMITTED. Leitores nunca bloqueiam escritores e escritores nunca bloqueiam leitores.

A configuração padrão READ COMMITTED do SQL Server usa bloqueio, o que significa que as consultas de leitura podem ficar bloqueadas enquanto aguardam a conclusão das transações de escrita. Se o aplicativo tiver um bloqueio maior após a migração, considere habilitar READ COMMITTED SNAPSHOT no banco de dados:

ALTER DATABASE [<your-database>]
SET READ_COMMITTED_SNAPSHOT ON;

Isso faz com que o SQL Server passe a usar o controle de versão de linha em READ COMMITTED (semelhante ao MVCC do PostgreSQL), em vez de usar bloqueios. Os leitores veem a última versão confirmada de uma linha sem esperar por gravadores ativos.

Note

READ COMMITTED SNAPSHOT requer espaço adicional tempdb para versões de linha. Teste sob carga realista antes de habilitar em produção. Para obter mais informações, consulte Gerenciamento de transações no mssql-django.

Etapa 5: Migrar dados

A estratégia de migração de dados depende do tamanho do conjunto de dados:

Conjuntos de dados pequenos (<500 MB)

Use Django's dumpdata/loaddata:

# On the source database
python manage.py dumpdata --natural-foreign --natural-primary -o data.json

# Switch settings.py to SQL Server, then:
python manage.py migrate
python manage.py loaddata data.json

Conjuntos de dados grandes (>500 MB)

Para migrações grandes, use ferramentas especializadas para evitar problemas de esgotamento de memória e tempo limite. O ORM do Django não é a ferramenta certa para cargas em massa nesta escala. Ignore-o para a movimentação de dados e permita que o Django gerencie o esquema e a lógica do aplicativo posteriormente.

Tool Mais adequado para
Assistente de Importação e Exportação do SQL Server Migrações de ambiente local para ambiente local com interface gráfica
Fábrica de dados do Azure Qualquer fonte para SQL do Azure, incluindo cenários híbridos
Serviço de Migração de Banco de Dados do Azure Migrações em larga escala com validação interna e reversão
cópia em massa com mssql-python e Apache Arrow Pipelines de Python personalizados que precisam de taxa de transferência máxima entre SQL Server, Banco de Dados SQL do Azure e banco de dados SQL no Fabric

Validação pós-migração

Após a migração, valide a consistência da semente de identidade para colunas de incremento automático:

-- Check identity seed and current value for all tables
SELECT 
    TABLE_NAME,
    IDENT_SEED(TABLE_SCHEMA + '.' + TABLE_NAME) AS IdentitySeed,
    IDENT_INCR(TABLE_SCHEMA + '.' + TABLE_NAME) AS IdentityIncrement,
    IDENT_CURRENT(TABLE_SCHEMA + '.' + TABLE_NAME) AS CurrentIdentity
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
    AND OBJECTPROPERTY(OBJECT_ID(TABLE_SCHEMA + '.' + TABLE_NAME), 'TableHasIdentity') = 1
ORDER BY TABLE_NAME;

Se CurrentIdentity exceder IdentitySeed + record_count, redefina a semente:

DBCC CHECKIDENT ('your_table', RESEED, new_seed);