Pular para o conteúdo
Início do IntoSQL

Converta SQL Server para PostgreSQL

Solte o script que o Generate Scripts do SSMS escreve com schema e dados, em .sql ou .sql.gz, UTF-16 ou UTF-8, e baixe um script do PostgreSQL com as mesmas tabelas, chaves, índices e dados. Cada valor que o PostgreSQL não aceita como está, e cada objeto que ele não traz, aparece no relatório.

Seu arquivo
sqlshop_2024_sqlserver.sqlArquivo de exemplo, 11 kB
Seu banco de dados

18 linhas convertidas, 3 correções, nenhuma rejeitada

Mostrar

Tabelas em shop_2024_sqlserver.sqlDump do SQL Server · gerado por SQL Server Management Objects · utf-8

  • orders10 linhas2
    11 colunas
    idinteger not null
    customer_idinteger not null
    statusvarchar(10) not null
    totalnumeric(19,4) not null
    itemssmallint not null
    ordered_attimestamp(0) not null
    shipped_attimestamp(6)
    notetext
    detailstext
    order_refuuid not null
    total_with_taxnumeric(12,2)
  • customers8 linhas1
    8 colunas
    idinteger not null
    namevarchar(100) not null
    emailvarchar(200) not null
    countryvarchar(2) not null
    is_activeboolean not null
    signed_update
    created_attimestamptz(0) not null
    row_versionbytea

Não convertidos

  • Visão paid_orders
  • Gatilho orders_no_negative

Cada banco de dados escreve estes objetos na sua própria linguagem. Reescreva-os para o PostgreSQL.

-- Written by IntoSQL from a SQL Server dump. Load it with: psql -v ON_ERROR_STOP=1 -f <file>
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SET check_function_bodies = false;
SET client_min_messages = warning;
SET synchronous_commit = off;
SET maintenance_work_mem = '512MB';

CREATE TABLE orders (
    id integer GENERATED BY DEFAULT AS IDENTITY NOT NULL,
    customer_id integer NOT NULL,
    status varchar(10) DEFAULT 'pending' NOT NULL,
    total numeric(19,4) NOT NULL,
    items smallint DEFAULT 1 NOT NULL,
    ordered_at timestamp(0) NOT NULL,
    shipped_at timestamp(6),
    note text,
    details text,
    order_ref uuid DEFAULT (gen_random_uuid()::text) NOT NULL,
    total_with_tax numeric(12,2) GENERATED ALWAYS AS ((cast(total * (1.16) AS numeric(12,2)))::numeric(12,2)) STORED,
    CONSTRAINT orders_items_check CHECK (items >= 0),
    CONSTRAINT orders_check2 CHECK (status = 'cancelled' OR status = 'shipped' OR status = 'paid' OR status = 'pending'),
    CONSTRAINT orders_check3 CHECK (total >= (0))
);

CREATE TABLE customers (
    id integer GENERATED BY DEFAULT AS IDENTITY NOT NULL,
    name varchar(100) NOT NULL,
    email varchar(200) NOT NULL,
    country varchar(2) DEFAULT 'US' NOT NULL,
    is_active boolean DEFAULT true NOT NULL,
    signed_up date,
    created_at timestamptz(0) DEFAULT CURRENT_TIMESTAMP NOT NULL,
    row_version bytea
);

COPY customers (id, name, email, country, is_active, signed_up, created_at) FROM stdin;
1	Ana Martínez	ana@example.com	MX	t	2023-01-15	2023-01-15 10:24:00.000000+00:00
2	Zoë Müller	zoe@example.de	DE	t	2023-02-03	2023-02-03 08:11:42.000000+00:00
3	José Peña	jose@example.es	ES	f	2023-03-21	2023-03-21 19:05:17.000000+00:00
4	李雷	lilei@example.cn	CN	t	2023-05-09	2023-05-09 02:40:00.000000+00:00
5	Noah O'Brien	noah@example.ie	IE	t	\N	2023-06-30 14:00:00.000000+00:00
6	Amélie Laurent	amelie@example.fr	FR	t	2024-01-02	2024-01-02 09:30:00.000000+00:00
7	Ravi Patel	ravi@example.in	IN	f	2024-02-29	2024-02-29 23:59:59.000000+00:00
8	Sofia Rossi 🌻	sofia@example.it	IT	t	2024-04-12	2024-04-12 12:12:12.000000+00:00
\.

COPY orders (id, customer_id, status, total, items, ordered_at, shipped_at, note, details, order_ref) FROM stdin;
1	1	shipped	129.9000	3	2024-03-01T10:00:00.000000	2024-03-02T16:30:00.123456	\N	{"gift": false}	0b7a4c2e-3f1d-4e8a-9c55-1a2b3c4d5e6f
2	2	paid	54.0000	1	2024-03-02T11:15:00.000000	\N	Gift wrap 🎁	{"gift": true, "wrap": "red"}	1c8b5d3f-4a2e-4f9b-8d66-2b3c4d5e6f70
3	1	cancelled	12.5000	1	2024-03-03T09:45:00.000000	\N	Customer changed their mind	\N	2d9c6e4a-5b3f-4a0c-9e77-3c4d5e6f7081
4	4	shipped	980.0000	12	2024-03-05T02:10:00.000000	2024-03-07T08:00:00.000000	请小心轻放	{"fragile": true}	3e0d7f5b-6c4a-4b1d-8f88-4d5e6f708192
5	5	pending	45.7500	2	2024-03-08T17:20:00.000000	\N	Leave at the door; ring twice	\N	4f1e806c-7d5b-4c2e-9a99-5e6f708192a3
6	6	shipped	310.4000	5	2024-03-10T13:00:00.000000	2024-03-11T09:00:00.000000	Fragile: "glass"	{"fragile": true}	50f2917d-8e6c-4d3f-8baa-6f708192a3b4
7	8	paid	76.2000	2	2024-03-11T18:45:00.000000	\N	\N	\N	6103a28e-9f7d-4e40-9cbb-708192a3b4c5
8	2	shipped	19.9900	1	2024-03-12T08:00:00.000000	9999-12-31T23:59:59.999999	Shipped date set to the maximum by an old import	\N	7214b39f-a08e-4f51-8dcc-8192a3b4c5d6
9	3	shipped	64.0000	2	2024-03-14T15:30:00.000000	2024-03-15T10:00:00.000000	Two parcels	{"parcels": [1, 2]}	8325c4a0-b19f-4062-9edd-92a3b4c5d6e7
10	7	paid	1499.0000	1	2024-03-15T21:05:00.000000	\N	C:\\Users\\ravi\\invoice.pdf	\N	9436d5b1-c2a0-4173-8fee-a3b4c5d6e7f8
\.


-- Keys, indexes and constraints, after the rows so each builds once.
CREATE UNIQUE INDEX orders_pkey ON orders (id);
CREATE INDEX orders_idx_orders_customer ON orders (customer_id);
CREATE INDEX orders_idx_orders_status_date ON orders (status, ordered_at);
CREATE UNIQUE INDEX customers_pkey ON customers (id);
CREATE UNIQUE INDEX customers_email ON customers (email);
ALTER TABLE orders ADD CONSTRAINT orders_pkey PRIMARY KEY USING INDEX orders_pkey;
ALTER TABLE customers ADD CONSTRAINT customers_pkey PRIMARY KEY USING INDEX customers_pkey;
ALTER TABLE customers ADD CONSTRAINT customers_email UNIQUE USING INDEX customers_email;
ALTER TABLE orders ADD CONSTRAINT orders_fkey FOREIGN KEY (customer_id) REFERENCES customers (id) NOT VALID;
DO $f$ BEGIN
    ALTER TABLE orders VALIDATE CONSTRAINT orders_fkey;
EXCEPTION WHEN foreign_key_violation THEN
    RAISE WARNING 'foreign key % has rows without a parent: it stays NOT VALID, and new rows are checked', 'orders_fkey';
END $f$;
SELECT setval(pg_get_serial_sequence('orders', 'id'), LEAST(GREATEST(COALESCE((SELECT max(id) FROM orders)::numeric, 0) + 1, 1), 2147483647)::bigint, false);
SELECT setval(pg_get_serial_sequence('customers', 'id'), LEAST(GREATEST(COALESCE((SELECT max(id) FROM customers)::numeric, 0) + 1, 1), 2147483647)::bigint, false);
COMMENT ON TABLE customers IS 'People who bought at least once';

Correções

  1. "items" de orders é sem sinal, então virou smallint com um CHECK de que não é negativa.
  2. "shipped_at" de orders é datetime2(7), com mais dígitos de segundo do que o PostgreSQL guarda, então vira timestamp(6) e os últimos dígitos são cortados.
  3. "row_version" de customers é uma versão de linha que o SQL Server define sozinho; o dump não tem valores para ela, então vira bytea e fica vazia.

Para revisar

  • 6 colunas de texto comparam sem diferenciar maiúsculas na origem; o PostgreSQL compara de forma exata, então chaves únicas e buscas podem se comportar de outro jeito. Use uma collation ou um tipo de coluna sem diferenciação de maiúsculas nas colunas que precisarem.
  • 2 visões, gatilhos, rotinas ou eventos não foram convertidos; o relatório lista cada um. Recrie-os manualmente no PostgreSQL.
  • O CHECK check1 de orders não pode ser escrito para o PostgreSQL (function isjson), então não é criado. Escreva o CHECK manualmente se ele for importante.
  • O índice idx_orders_pending de orders usa uma expressão que não pode ser escrita para o PostgreSQL (filtered index), então não é criado. Crie o índice manualmente se as consultas precisarem dele.

Seu arquivo é convertido neste computador e nunca é enviado.

Outros exemplos:

O que muda do SQL Server para o PostgreSQL

Cada linha é uma regra que o conversor aplica, com a linha do relatório que ele escreve quando a regra muda algo nos seus dados.

  • bit

    boolean

    bit guarda 1 e 0, que são o true e o false do PostgreSQL.

  • tinyint

    smallint com um CHECK de que não é negativo

    O tinyint do SQL Server vai de 0 a 255; o menor inteiro do PostgreSQL tem sinal, então um CHECK mantém o intervalo.

    Linha do relatório: unsigned_widened

  • char(n), varchar(n), nchar(n), nvarchar(n), varchar(max), text

    varchar(n) e text

    O text do PostgreSQL comporta qualquer caractere, então varchar e nvarchar são o mesmo tipo.

  • decimal(p,s), money, smallmoney

    numeric(p,s); money como numeric(19,4)

    Cada dígito é mantido, e money com suas quatro casas decimais.

  • datetime, datetime2, smalldatetime

    timestamp(p)

    Um datetime é a leitura de um relógio de parede, como um timestamp sem fuso horário.

  • datetime2(7), time(7) and datetimeoffset(7)

    seis dígitos de segundo, o sétimo cortado

    O PostgreSQL guarda microssegundos; o sétimo dígito (100 nanossegundos) é cortado, nunca arredondado, então nenhum valor passa para o segundo ou o dia seguinte.

    Linha do relatório: fraction_cut

  • datetimeoffset

    timestamptz, os mesmos instantes

    timestamptz mantém o instante; o PostgreSQL o mostra no fuso horário da sessão em vez do fuso que cada valor tinha.

  • time

    time(p)

    Os mesmos horários do dia.

  • json (SQL Server 2025)

    jsonb

    Os mesmos valores JSON.

  • uniqueidentifier

    uuid

    Os mesmos identificadores, escritos em minúsculas.

  • binary, varbinary, image

    bytea

    Bytes continuam sendo bytes.

  • geometry, geography

    bytea com os bytes próprios do SQL Server

    O SSMS escreve valores espaciais na serialização do SQL Server, que é mantida byte a byte.

    Linha do relatório: spatial_as_native

  • rowversion, timestamp

    bytea, sem valores

    O SQL Server define a versão de linha sozinho, e o SSMS não escreve valores para ela no script.

    Linha do relatório: rowversion_empty

  • sql_variant, hierarchyid, vector

    text

    O PostgreSQL não tem um tipo equivalente; sql_variant mantém o texto de cada valor e hierarchyid o seu caminho, como /1/2/. xml continua xml.

    Linha do relatório: type_replaced

  • collations that ignore case (_CI_)

    comparação exata

    O PostgreSQL compara texto de forma exata, então colunas que ignoravam maiúsculas no SQL Server agora diferenciam Ana de ana.

    Linha do relatório: case_insensitive_collation

  • IDENTITY

    GENERATED BY DEFAULT AS IDENTITY, continuando depois do maior id

    Os ids copiados carregam como estão, e o contador continua depois do maior deles.

  • CREATE SEQUENCE

    CREATE SEQUENCE com as mesmas opções

    As sequências do PostgreSQL funcionam do mesmo jeito. O SSMS não escreve até onde uma sequência chegou, então ela começa onde foi criada.

  • computed columns

    colunas geradas, STORED

    O PostgreSQL 13 a 17 só armazena colunas geradas; a fórmula é a mesma, com CONCAT escrito para que NULL conte como vazio, como no SQL Server.

    Linha do relatório: virtual_as_stored

  • computed columns with functions PostgreSQL lacks

    uma coluna simples

    Uma fórmula que não pode ser escrita para o PostgreSQL deixa uma coluna simples e uma linha no relatório; o SSMS não escreve valores para colunas computadas.

    Linha do relatório: generated_not_translated

  • defaults with functions PostgreSQL lacks, and NEXT VALUE FOR

    sem valor padrão

    Um valor padrão que não pode ser escrito para o PostgreSQL fica de fora e é informado no relatório.

    Linha do relatório: default_not_translated

  • CHECK constraints

    traduzidos

    Os mesmos CHECKs, testados à medida que cada linha carrega.

  • CHECK constraints with functions PostgreSQL lacks

    não criado

    Um CHECK que não pode ser escrito para o PostgreSQL fica de fora e é informado no relatório.

    Linha do relatório: check_skipped

  • CHECK constraints added WITH NOCHECK or disabled

    não criado

    O SQL Server não aplica esses CHECKs, então as linhas podem violá-los.

    Linha do relatório: check_not_enforced

  • filtered and columnstore indexes

    não criado

    O IntoSQL escreve índices b-tree sobre colunas; crie os outros de novo depois da carga.

    Linha do relatório: index_skipped

  • foreign keys

    chaves estrangeiras, depois das linhas

    As linhas carregam em qualquer ordem, e as chaves as verificam depois.

  • foreign keys to tables the dump doesn't create

    não criado

    Uma chave não pode apontar para uma tabela que não existe.

    Linha do relatório: foreign_key_skipped

  • tables on a partition scheme

    uma tabela com as linhas de todas as partições

    As linhas são as mesmas; particione a tabela de novo no PostgreSQL se precisar.

    Linha do relatório: partitions_dropped

  • temporal tables (SYSTEM_VERSIONING)

    duas tabelas: as linhas atuais e o histórico

    A tabela e sua tabela de histórico são copiadas como tabelas simples; o PostgreSQL não mantém o histórico sozinho.

    Linha do relatório: system_versioning_dropped

  • NOT NULL columns with values that become NULL

    NOT NULL removido

    Uma coluna cujos valores tiveram de virar NULL não pode manter NOT NULL, senão a carga pararia.

    Linha do relatório: not_null_relaxed

  • views, functions, procedures, triggers, synonyms, types and partition functions

    listados no relatório

    O código deles é escrito em T-SQL, então eles são listados para você recriá-los.

    Linha do relatório: not_converted_objects

  • scripts without CREATE TABLE (data only)

    tipos deduzidos dos valores

    Um script só de dados tem apenas linhas, então os tipos vêm dos valores.

    Linha do relatório: no_schema

  • expressions in INSERT values

    NULL

    Um conversor que não executa um banco de dados não consegue avaliá-las.

    Linha do relatório: expression_value

  • types IntoSQL doesn't know

    text

    O tipo text aceita qualquer valor; mude o tipo depois da carga.

    Linha do relatório: unknown_type

  • dates that aren't valid

    NULL

    Um valor que não é uma data vira NULL e o relatório o conta.

    Linha do relatório: date_out_of_range

  • NUL characters in text

    removido

    O texto do PostgreSQL não aceita o caractere NUL. Ele é removido e o relatório conta os valores.

    Linha do relatório: nul_removed

  • text that isn't valid in its encoding

    os bytes inválidos como o caractere de substituição

    O texto do PostgreSQL deve ser UTF-8 válido.

    Linha do relatório: invalid_utf8_replaced

  • text decoded twice (ñ)

    copiado como está

    O script contém exatamente esses caracteres, então eles são copiados; o relatório os aponta.

    Linha do relatório: mojibake_suspected

No SQL ServerNo PostgreSQLLinha do relatório
bitbooleanbit guarda 1 e 0, que são o true e o false do PostgreSQL.
tinyintsmallint com um CHECK de que não é negativoO tinyint do SQL Server vai de 0 a 255; o menor inteiro do PostgreSQL tem sinal, então um CHECK mantém o intervalo.unsigned_widened
char(n), varchar(n), nchar(n), nvarchar(n), varchar(max), textvarchar(n) e textO text do PostgreSQL comporta qualquer caractere, então varchar e nvarchar são o mesmo tipo.
decimal(p,s), money, smallmoneynumeric(p,s); money como numeric(19,4)Cada dígito é mantido, e money com suas quatro casas decimais.
datetime, datetime2, smalldatetimetimestamp(p)Um datetime é a leitura de um relógio de parede, como um timestamp sem fuso horário.
datetime2(7), time(7) and datetimeoffset(7)seis dígitos de segundo, o sétimo cortadoO PostgreSQL guarda microssegundos; o sétimo dígito (100 nanossegundos) é cortado, nunca arredondado, então nenhum valor passa para o segundo ou o dia seguinte.fraction_cut
datetimeoffsettimestamptz, os mesmos instantestimestamptz mantém o instante; o PostgreSQL o mostra no fuso horário da sessão em vez do fuso que cada valor tinha.
timetime(p)Os mesmos horários do dia.
json (SQL Server 2025)jsonbOs mesmos valores JSON.
uniqueidentifieruuidOs mesmos identificadores, escritos em minúsculas.
binary, varbinary, imagebyteaBytes continuam sendo bytes.
geometry, geographybytea com os bytes próprios do SQL ServerO SSMS escreve valores espaciais na serialização do SQL Server, que é mantida byte a byte.spatial_as_native
rowversion, timestampbytea, sem valoresO SQL Server define a versão de linha sozinho, e o SSMS não escreve valores para ela no script.rowversion_empty
sql_variant, hierarchyid, vectortextO PostgreSQL não tem um tipo equivalente; sql_variant mantém o texto de cada valor e hierarchyid o seu caminho, como /1/2/. xml continua xml.type_replaced
collations that ignore case (_CI_)comparação exataO PostgreSQL compara texto de forma exata, então colunas que ignoravam maiúsculas no SQL Server agora diferenciam Ana de ana.case_insensitive_collation
IDENTITYGENERATED BY DEFAULT AS IDENTITY, continuando depois do maior idOs ids copiados carregam como estão, e o contador continua depois do maior deles.
CREATE SEQUENCECREATE SEQUENCE com as mesmas opçõesAs sequências do PostgreSQL funcionam do mesmo jeito. O SSMS não escreve até onde uma sequência chegou, então ela começa onde foi criada.
computed columnscolunas geradas, STOREDO PostgreSQL 13 a 17 só armazena colunas geradas; a fórmula é a mesma, com CONCAT escrito para que NULL conte como vazio, como no SQL Server.virtual_as_stored
computed columns with functions PostgreSQL lacksuma coluna simplesUma fórmula que não pode ser escrita para o PostgreSQL deixa uma coluna simples e uma linha no relatório; o SSMS não escreve valores para colunas computadas.generated_not_translated
defaults with functions PostgreSQL lacks, and NEXT VALUE FORsem valor padrãoUm valor padrão que não pode ser escrito para o PostgreSQL fica de fora e é informado no relatório.default_not_translated
CHECK constraintstraduzidosOs mesmos CHECKs, testados à medida que cada linha carrega.
CHECK constraints with functions PostgreSQL lacksnão criadoUm CHECK que não pode ser escrito para o PostgreSQL fica de fora e é informado no relatório.check_skipped
CHECK constraints added WITH NOCHECK or disablednão criadoO SQL Server não aplica esses CHECKs, então as linhas podem violá-los.check_not_enforced
filtered and columnstore indexesnão criadoO IntoSQL escreve índices b-tree sobre colunas; crie os outros de novo depois da carga.index_skipped
foreign keyschaves estrangeiras, depois das linhasAs linhas carregam em qualquer ordem, e as chaves as verificam depois.
foreign keys to tables the dump doesn't createnão criadoUma chave não pode apontar para uma tabela que não existe.foreign_key_skipped
tables on a partition schemeuma tabela com as linhas de todas as partiçõesAs linhas são as mesmas; particione a tabela de novo no PostgreSQL se precisar.partitions_dropped
temporal tables (SYSTEM_VERSIONING)duas tabelas: as linhas atuais e o históricoA tabela e sua tabela de histórico são copiadas como tabelas simples; o PostgreSQL não mantém o histórico sozinho.system_versioning_dropped
NOT NULL columns with values that become NULLNOT NULL removidoUma coluna cujos valores tiveram de virar NULL não pode manter NOT NULL, senão a carga pararia.not_null_relaxed
views, functions, procedures, triggers, synonyms, types and partition functionslistados no relatórioO código deles é escrito em T-SQL, então eles são listados para você recriá-los.not_converted_objects
scripts without CREATE TABLE (data only)tipos deduzidos dos valoresUm script só de dados tem apenas linhas, então os tipos vêm dos valores.no_schema
expressions in INSERT valuesNULLUm conversor que não executa um banco de dados não consegue avaliá-las.expression_value
types IntoSQL doesn't knowtextO tipo text aceita qualquer valor; mude o tipo depois da carga.unknown_type
dates that aren't validNULLUm valor que não é uma data vira NULL e o relatório o conta.date_out_of_range
NUL characters in textremovidoO texto do PostgreSQL não aceita o caractere NUL. Ele é removido e o relatório conta os valores.nul_removed
text that isn't valid in its encodingos bytes inválidos como o caractere de substituiçãoO texto do PostgreSQL deve ser UTF-8 válido.invalid_utf8_replaced
text decoded twice (ñ)copiado como estáO script contém exatamente esses caracteres, então eles são copiados; o relatório os aponta.mojibake_suspected

Carregue o script no PostgreSQL

O script cria as tabelas, copia as linhas e depois adiciona chaves, índices e chaves estrangeiras, então carrega rápido e para no primeiro erro.

psql -v ON_ERROR_STOP=1 -d mydb -f sql_server.postgresql.sql

As chaves estrangeiras são adicionadas como NOT VALID e depois validadas. Se uma linha aponta para uma linha que não existe, o script informa qual restrição, em vez de falhar no meio do caminho.

Para um dump grande, crie o banco de dados antes e execute o script com o psql na mesma máquina do servidor.

O IntoSQL Pro carrega o arquivo direto no PostgreSQL pelo app para desktop ou pela linha de comando, sem escrever um script.

Gere o dump do SQL Server para o melhor resultado

O conversor lê o que o dump contém. Estas opções mantêm mais dos seus dados nele:

  • No SSMS, clique com o botão direito no banco de dados, Tasks, Generate Scripts, e escolha as tabelas. dbatools, mssql-scripter e outras ferramentas feitas sobre a mesma biblioteca escrevem o mesmo script.
  • Em Advanced, defina Types of data to script como Schema and data. Um script só do schema tem tabelas sem linhas.
  • Salve como Unicode, o padrão do SSMS, ou como UTF-8: os dois são lidos do mesmo jeito, e gzip também funciona.

O que não é convertido

Visões, funções, procedimentos, gatilhos, sinônimos, regras e políticas de segurança são escritos em T-SQL. Eles aparecem no relatório pelo nome, nunca são descartados em silêncio, para que você possa reescrevê-los para o PostgreSQL.

Perguntas sobre SQL Server para PostgreSQL

Não encontrou a resposta? Escreva para nós pela página de contato e uma pessoa responde. Página de contato

Meu dump é enviado?

Não. O conversor roda no seu navegador e lê o dump do seu disco em partes, então ele nunca sai do seu computador. O app para desktop e a linha de comando também convertem no seu computador.

Qual o tamanho máximo do dump?

O conversor nunca guarda o dump inteiro na memória: ele lê o arquivo duas vezes, por intervalos, e escreve o script à medida que avança. Dumps de vários gigabytes são convertidos no navegador, no app para desktop e com a linha de comando.

Ele lê o arquivo UTF-16 que o SSMS salva?

Sim. O SSMS salva scripts em UTF-16 por padrão, e o conversor lê UTF-16 e UTF-8 do mesmo jeito, com ou sem gzip, com GO entre os lotes.

De quais versões do SQL Server o script pode vir?

Scripts que o SSMS, o dbatools ou o mssql-scripter escrevem a partir do SQL Server 2017. Cada script de teste vem do SQL Server 2017, 2022 e 2025 e é comparado com a origem célula por célula.

Os valores IDENTITY são mantidos?

Sim. As colunas IDENTITY viram colunas de identidade, cada linha mantém seu id, e o próximo id continua depois do maior. As sequências são criadas com as mesmas opções.

O que acontece com money, datetimeoffset e outros tipos do SQL Server?

bit vira boolean, money numeric(19,4), uniqueidentifier uuid, xml xml, e datetimeoffset timestamptz. datetime2 mantém seis dígitos de segundo, com o sétimo cortado. Colunas que ignoravam maiúsculas comparam de forma exata, e o relatório diz quais.

E os procedimentos, gatilhos e visões?

Eles aparecem no relatório pelo nome e não são convertidos, porque cada banco de dados os escreve na sua própria linguagem.

Em quais versões do PostgreSQL o script carrega?

PostgreSQL 13 a 18. O mesmo script carrega em cada uma delas e para no primeiro erro se algo der errado.