Migrate SQLite to SQL Server
Beta — live-tested pathMigrating from SQLite (the embedded database that ships inside everything) to SQL Server (Microsoft's enterprise relational database) means every table, column type, key, index and row has to survive two engines' different opinions about data. This is a cross-model migration — rows and relations are preserved as structured documents — and the conversion rules are explicit, not guessed. DBShifts converts the schema with deterministic rules, transfers data in parallel batches, and validates the result with per-table row counts and type-aware checksums.
Free tier · no credit card
SQLite vs SQL Server
SQLite
the embedded database that ships inside everything.
SQL Server
Microsoft's enterprise relational database.
How the migration works
Connect
Point DBShifts at your source and target. Credentials stay encrypted; SSH tunnels supported for private databases.
Analyze
Automatic schema introspection produces a migration plan: what converts automatically, what migrates with warnings, what needs human review.
Migrate
Schema is created on the target, data transfers in parallel batches with constraints deferred, indexes rebuilt after load.
Validate
Per-table row counts, type-aware checksums on both sides, FK integrity — plus a fidelity report listing anything lossy.
SQLite to SQL Server data type mapping
Pulled directly from DBShifts's own conversion rules — not a general reference table, this is what actually runs.
| SQLite | SQL Server |
|---|---|
| INTEGER | BIGINT |
| REAL | FLOAT(53) |
| TEXT | NVARCHAR(MAX) |
| BLOB | VARBINARY(MAX) |
| NUMERIC | FLOAT(53) |
| BOOLEAN | BIT |
| DATETIME | DATETIME2 |
| VARCHAR(255) | NVARCHAR(255) |
Example: SQLite to SQL Server schema conversion
SQLite
CREATE TABLE orders ( id INTEGER PRIMARY KEY AUTOINCREMENT, customer_id INTEGER NOT NULL, total NUMERIC NOT NULL, is_gift BOOLEAN NOT NULL DEFAULT 0, notes TEXT, placed_at DATETIME NOT NULL );
SQL Server
IF OBJECT_ID(N'orders', 'U') IS NULL
CREATE TABLE [orders] (
[id] BIGINT NOT NULL,
[customer_id] BIGINT NOT NULL,
[total] FLOAT(53) NOT NULL,
[is_gift] BIT,
[notes] NVARCHAR(MAX),
[placed_at] DATETIME2 NOT NULL,
CONSTRAINT [PK_orders] PRIMARY KEY ([id])
);Everything SQLite did not enforce, SQL Server will
SQLite's type affinity means a column declared INTEGER may genuinely contain text, and a VARCHAR(10) may contain much longer values. SQL Server enforces both. The result is that a migration which looks trivial by schema size can fail row by row on data that was never valid against its own declared types.
Expect this to surface as failed inserts rather than as conversion errors, because the schema converts cleanly. Profiling the actual values per column before the load, rather than trusting the declared types, is what makes this migration predictable.
The same applies to NULL in primary keys. SQLite permits NULL in a PRIMARY KEY column that is not INTEGER PRIMARY KEY, which SQL Server does not allow at all.
Dates stored as text
SQLite has no date type, so dates arrive as text, as integers holding Unix time, or as floats holding Julian day numbers, depending on what the application chose. All three are common and they cannot be distinguished from the schema.
The conversion to DATETIME2 has to know which convention was used, and getting it wrong produces either a parse failure or, worse, plausible dates that are decades out. Sampling the actual values is the only reliable way to tell.
Going from a file to a server
This migration usually accompanies a change in how the application is deployed: from an embedded database shipped with the product to a shared server that several instances or users hit at once. That change brings requirements the SQLite schema never had to express, notably concurrent access, authentication and backup.
It is worth adding what the file-based schema left out at the same time: appropriate indexes for the new access patterns, explicit NOT NULL where the application always sets a value, and the foreign keys that SQLite may never have enforced.
SQLite → SQL Server conversion notes
Engine-specific rules baked into the conversion and transfer pipeline — verified by live certification of this exact pair.
- INTEGER columns are 64-bit — DBShifts maps them to BIGINT so large IDs don't overflow 32-bit INT targets.
- Typeless and mixed-affinity columns (SQLite's dynamic typing) are inferred, stringified safely, and flagged.
- NUMERIC affinity values are read exactly, not through float round-trips.
- IDENTITY_INSERT is managed per table so explicit IDs from the source load correctly, then counters are reseeded with DBCC CHECKIDENT.
- Binary columns always carry an explicit length — bare VARBINARY (which means 1 byte) never reaches the target.
- TRUNCATE falls back to DELETE on FK-referenced tables automatically.
Frequently asked questions
Is SQLite to SQL Server migration production-ready in DBShifts?
SQLite to SQL Server is a live-verified beta pair: it passed the same certification suite as every other pair — a real migration with edge-case data validated by row counts and checksums — and ships with a post-migration fidelity report you can audit before cutover.
How does DBShifts verify the SQLite to SQL Server migration was correct?
Three layers: per-table row counts on both sides, an order-independent type-aware checksum of row data (canonicalized so engine representation differences don't false-alarm), and FK integrity checks on the target. Rows that fail to insert are quarantined with the exact error — never silently dropped — and can be fixed and retried from the UI.
What happens to SQLite types that SQL Server doesn't have?
They convert by deterministic rules with a recorded decision: a native equivalent where one exists, a portable fallback (TEXT/JSON/DECIMAL) where one doesn't. Every lossy conversion appears in the migration plan before you run and in the fidelity report after. You can override any mapping per column.
Can I keep SQLite and SQL Server in sync after the initial migration?
SQLite has no replication log, so continuous CDC isn't available from it — but incremental sync re-runs transfer only changed rows using a per-table sync key.
Do I need to write any SQL or scripts for SQLite to SQL Server?
No. Connect both databases, review the generated migration plan (what's automatic, what migrates with warnings, what needs manual review — typically triggers and stored procedures), and run. Procedural code is transpiled best-effort and queued for human review rather than auto-applied.
What's the hardest part of moving SQLite to SQL Server?
The data model itself differs (embedded → sql), so rows and relations are restructured into documents with explicit type rules. DBShifts surfaces every inference and lossy conversion in the migration plan before you run, so nothing is guessed silently.
Go deeper
Related migration paths
Ready to move SQLite to SQL Server?
Set up in under two minutes. Validation and rollback included.
Start Free Migration