---
title: "SQLite to PostgreSQL data types"
description: "Every SQLite data type that PostgreSQL stores differently, what the converter writes for it, when, and the report line."
canonical: https://intosql.com/docs/types/sqlite-to-postgresql
last_updated: 2026-10-15
---

# SQLite to PostgreSQL data types

Each row is a type from SQLite that PostgreSQL stores differently: what the PostgreSQL script gets, why, and the line the report writes about it. The rows come from the converter's own rules, so this page matches what it does.

**Convert in the browser:** [SQLite to PostgreSQL](/sqlite-to-postgresql) opens the converter set up for this pair. The [SQLite to PostgreSQL migration guide](/docs/migrations/sqlite-to-postgresql) covers dumping, loading and the rules for keys, indexes and names.

A report line is a fix when the converter changed something and lists it, or a problem when a value or object is worth a look.

## Numbers

| In SQLite | In PostgreSQL | Why | Report line |
| --- | --- | --- | --- |
| DECIMAL(p,s), NUMERIC | the exact type when every value fits it, else a double | SQLite stores these as integers or doubles; a declared precision holds only when the values fit it. | None |

## Booleans and bits

| In SQLite | In PostgreSQL | Why | Report line |
| --- | --- | --- | --- |
| BOOLEAN, BOOL | boolean | When every value is 0 or 1; a column that also holds other values keeps them as numbers or text. | None |

## Text

| In SQLite | In PostgreSQL | Why | Report line |
| --- | --- | --- | --- |
| TEXT, VARCHAR(n), CHAR(n), CLOB | varchar(n) when every value fits the declared length, else text | SQLite never enforces a length; a declared length holds only when every value fits it. | None |
| NUL characters in text | removed | The sqlite3 shell and Python cut text at a NUL character when they dump it, so only what precedes it is in the dump. PostgreSQL text can't hold one either. | `nul_removed` (problem) |
| text that isn't valid UTF-8 | the bad bytes as the replacement character | Dumps write such text as raw bytes; the script is UTF-8. | `invalid_utf8_replaced` (problem) |

## Dates and times

| In SQLite | In PostgreSQL | Why | Report line |
| --- | --- | --- | --- |
| DATE, DATETIME, TIMESTAMP holding ISO 8601 text | date, timestamp | When every value is a date or a date and time; epoch numbers and other text keep their values as they are. | None |

## Binary

| In SQLite | In PostgreSQL | Why | Report line |
| --- | --- | --- | --- |
| BLOB, and columns holding bytes | bytea | Bytes stay bytes; text and numbers in the same column are kept as their bytes. | None |

## JSON, spatial and other types

| In SQLite | In PostgreSQL | Why | Report line |
| --- | --- | --- | --- |
| declared types (any text: VARCHAR(255), DATETIME, BOOLEAN, JSON or none) | the type every value in the column fits | SQLite keeps any value in any column, so the declared type is a hint: each column gets the type all of its values fit, and a column holding mixed values keeps their text. | None |
| JSON holding JSON text | jsonb | When every value is a JSON object or array. | None |
| Infinity in REAL columns | Infinity, as PostgreSQL's double keeps it | PostgreSQL's doubles hold infinity. | None |

## Counters and identities

| In SQLite | In PostgreSQL | Why | Report line |
| --- | --- | --- | --- |
| INTEGER PRIMARY KEY, AUTOINCREMENT | GENERATED BY DEFAULT AS IDENTITY, continuing after the highest id or sqlite_sequence's | Only a column declared exactly INTEGER PRIMARY KEY is the rowid; every row keeps its id, and the counter starts after the highest id ever handed out. | None |

## Other pairs

- SQLite into [MySQL](/docs/types/sqlite-to-mysql), [MariaDB](/docs/types/sqlite-to-mariadb), [SQLite](/docs/types/sqlite-to-sqlite), [SQL Server](/docs/types/sqlite-to-sql-server), [Oracle](/docs/types/sqlite-to-oracle)
- Into PostgreSQL from [MySQL](/docs/types/mysql-to-postgresql), [MariaDB](/docs/types/mariadb-to-postgresql), [PostgreSQL](/docs/types/postgresql-to-postgresql), [SQL Server](/docs/types/sql-server-to-postgresql), [Oracle](/docs/types/oracle-to-postgresql)
- [Every pair](/docs/types#from-one-database-to-another)
