---
title: "Move a SQL Server script to another version"
description: "Convert an SSMS script from SQL Server 2017 or later into one that loads on SQL Server 2017 to 2025, with the same tables, keys and data, and a report of every change."
canonical: https://intosql.com/sql-server-to-sql-server
last_updated: 2026-10-15
---

# Move a SQL Server script to another version

Drop the script SSMS's Generate Scripts writes with schema and data, as .sql or .sql.gz, UTF-16 or UTF-8, and download one that loads on SQL Server 2017 to 2025, whichever version wrote it. Identities, collations and types such as xml and hierarchyid stay as they are, and every change is listed in the report.

[SQL Server to SQL Server migration guide](https://intosql.com/docs/migrations/sql-server-to-sql-server)

[SQL Server to SQL Server data types](https://intosql.com/docs/types/sql-server-to-sql-server)

## What changes between the file and the script

Each row is a rule the converter applies, with the report line it writes when the rule changes something in your data.

| In the file | In the script | Report line |
| --- | --- | --- |
| bit | bit |  |
| char(n), varchar(n), nchar(n), nvarchar(n), varchar(max), text, ntext | nchar(n), nvarchar(n) and nvarchar(max), with each column's collation |  |
| column collations | the same collation on each column |  |
| decimal(p,s), money, smallmoney | decimal(p,s); money as decimal(19,4) |  |
| datetime, datetime2, smalldatetime | datetime2(p) |  |
| datetimeoffset | datetimeoffset, with each value's offset |  |
| time | time(p) |  |
| dates that aren't valid | NULL | `date_out_of_range` |
| json (SQL Server 2025) | nvarchar(max) |  |
| uniqueidentifier | uniqueidentifier |  |
| binary, varbinary, image | binary(n), varbinary(n) and varbinary(max) |  |
| xml, sql_variant, hierarchyid, geometry, geography | the same types |  |
| rowversion, timestamp | binary(8), empty | `rowversion_empty` |
| IDENTITY | IDENTITY, continuing after the highest id |  |
| CREATE SEQUENCE | CREATE SEQUENCE with the same options |  |
| computed columns | the same computed columns, PERSISTED as in the source |  |
| computed columns with functions IntoSQL doesn't write | a plain column | `generated_not_translated` |
| defaults with functions IntoSQL doesn't write, and NEXT VALUE FOR | no default | `default_not_translated` |
| CHECK constraints | translated |  |
| CHECK constraints with functions IntoSQL doesn't write | not created | `check_skipped` |
| CHECK constraints added WITH NOCHECK or disabled | not created | `check_not_enforced` |
| filtered and columnstore indexes | not created | `index_skipped` |
| foreign keys | after the data WITH NOCHECK, then checked with a warning on orphans |  |
| ON DELETE or ON UPDATE that cascades in a cycle or along a second path | NO ACTION | `foreign_key_action_dropped` |
| foreign keys to tables the dump doesn't create | not created | `foreign_key_skipped` |
| tables on a partition scheme | one table with every partition's rows | `partitions_dropped` |
| temporal tables (SYSTEM_VERSIONING) | two tables: the current rows and the history | `system_versioning_dropped` |
| NOT NULL columns with values that become NULL | NOT NULL dropped | `not_null_relaxed` |
| views, functions, procedures, triggers, synonyms, types and partition functions | listed in the report | `not_converted_objects` |
| scripts without CREATE TABLE (data only) | types read from the values | `no_schema` |
| expressions in INSERT values | NULL | `expression_value` |
| types IntoSQL doesn't know | nvarchar(max) | `unknown_type` |
| NUL characters in text | kept |  |
| text that isn't valid in its encoding | the bad bytes as the replacement character | `invalid_utf8_replaced` |
| text decoded twice (Ã±) | copied as it is | `mojibake_suspected` |

## Load the script into SQL Server

The script creates the tables, copies the rows, then adds keys, indexes and foreign keys, so it loads fast and stops at the first error.

```shell
sqlcmd -b -f 65001 -S localhost -d mydb -i sql_server.sql_server.sql
```

Foreign keys are added WITH NOCHECK and then checked. If a row points to a row that doesn't exist, the script says which constraint and leaves it unchecked, instead of failing half way.

For a large dump, run sqlcmd on the same machine as the server. Each batch of up to 1000 rows commits on its own, so the transaction log stays small.

## Dump SQL Server for the best result

The converter reads what the dump holds. These options keep more of your data in it:

- In SSMS, right-click the database, Tasks, Generate Scripts, and pick the tables. dbatools, mssql-scripter and other tools built on the same library write the same script.
- Under Advanced, set Types of data to script to Schema and data. A script of the schema alone has tables without rows.
- Save it as Unicode, SSMS's default, or as UTF-8: both are read the same way, and gzip works too.

## What isn't converted

Views, triggers, procedures, functions and other objects written in SQL Server's own language are listed in the report by name, never dropped silently, so you can check each one against the SQL Server version you load into before recreating it.

## Questions about moving SQL Server between versions

### Is my dump uploaded?

No. The converter runs in your browser and reads the dump from your disk in pieces, so it never leaves your computer. The desktop app and the command line convert on your computer too.

### How large can the dump be?

The converter never holds the whole dump in memory: it reads the file twice, by ranges, and writes the script as it goes. Multi-gigabyte dumps convert in the browser, in the desktop app and with the command line.

### Does it read the UTF-16 file SSMS saves?

Yes. SSMS saves scripts as UTF-16 by default, and the converter reads UTF-16 and UTF-8 alike, gzipped or not, with GO between batches.

### Which SQL Server versions can the script come from?

Scripts that SSMS, dbatools or mssql-scripter write from SQL Server 2017 on. Every test script comes from SQL Server 2017, 2022 and 2025 and is compared with its source cell by cell.

### Are IDENTITY values kept?

Yes. IDENTITY columns load with IDENTITY_INSERT, every row keeps its id, and the counter continues after the highest one. Sequences are created with the same options.

### What happens to money, datetimeoffset and other SQL Server types?

They stay as they are: xml, sql_variant, hierarchyid, geometry and geography included, and every text column keeps its collation. datetimeoffset values keep their offsets. rowversion columns are binary(8), because the script has no values for them.

### What about procedures, triggers and views?

They are listed in the report by name and not converted, so you can run their part of the original script once the tables are in.

### Which SQL Server versions does the script load on?

SQL Server 2017 to 2025, whichever version wrote the script. The same script loads on each of them, stopping at the first error if anything goes wrong.

## From SQL Server

- [SQL Server to PostgreSQL](https://intosql.com/sql-server-to-postgresql)
- [SQL Server to MySQL](https://intosql.com/sql-server-to-mysql)
- [SQL Server to MariaDB](https://intosql.com/sql-server-to-mariadb)
- [SQL Server to SQLite](https://intosql.com/sql-server-to-sqlite)
- [SQL Server to Oracle](https://intosql.com/sql-server-to-oracle)

## Into SQL Server

- [MySQL to SQL Server](https://intosql.com/mysql-to-sql-server)
- [MariaDB to SQL Server](https://intosql.com/mariadb-to-sql-server)
- [PostgreSQL to SQL Server](https://intosql.com/postgresql-to-sql-server)
- [SQLite to SQL Server](https://intosql.com/sqlite-to-sql-server)
- [Oracle to SQL Server](https://intosql.com/oracle-to-sql-server)

## Guide and every pair

- [SQL Server to SQL Server migration guide](https://intosql.com/docs/migrations/sql-server-to-sql-server)
- [SQL Server to SQL Server data types](https://intosql.com/docs/types/sql-server-to-sql-server)
- [Every database pair](https://intosql.com/database-migration)
