SQL Data Types Reference

Compare data types across PostgreSQL, MySQL, SQL Server, SQLite, and Oracle. Find the right equivalent when migrating schemas.

🔢 Numeric Types

ConceptPostgreSQLMySQLSQL ServerSQLiteOracle
16-bit integerSMALLINTSMALLINTSMALLINTINTEGERNUMBER(5)
32-bit integerINTEGER / INTINTINTINTEGERNUMBER(10)
64-bit integerBIGINTBIGINTBIGINTINTEGERNUMBER(19)
Auto-increment integerSERIAL / BIGSERIALINT AUTO_INCREMENTINT IDENTITY(1,1)INTEGER PRIMARY KEYNUMBER GENERATED ALWAYS AS IDENTITY
Fixed-point decimalNUMERIC(p,s) / DECIMAL(p,s)DECIMAL(p,s)DECIMAL(p,s) / NUMERIC(p,s)NUMERICNUMBER(p,s)
Single-precision floatREALFLOATREALREALBINARY_FLOAT
Double-precision floatDOUBLE PRECISIONDOUBLEFLOATREALBINARY_DOUBLE
Money / currencyMONEYDECIMAL(19,4)MONEY / SMALLMONEYNUMERICNUMBER(19,4)

⚠️ SQLite has no true BIGINT; it uses flexible typing. Oracle NUMBER without precision is a floating-point.

🔤 String Types

ConceptPostgreSQLMySQLSQL ServerSQLiteOracle
Fixed-length charCHAR(n)CHAR(n)CHAR(n)TEXTCHAR(n)
Variable-length stringVARCHAR(n)VARCHAR(n)VARCHAR(n) / NVARCHAR(n)TEXTVARCHAR2(n)
Unlimited/long textTEXTLONGTEXTVARCHAR(MAX) / TEXTTEXTCLOB
Unicode stringVARCHAR / TEXT (UTF-8 native)NVARCHAR / VARCHAR with utf8mb4NVARCHAR(n)TEXT (UTF-8 native)NVARCHAR2(n)
Binary dataBYTEABLOB / BINARYVARBINARY(n)BLOBRAW / BLOB

⚠️ Oracle recommends VARCHAR2 over VARCHAR. SQLite uses dynamic typing; TEXT accepts any length. MySQL VARCHAR max is 65,535 bytes.

📅 Date & Time Types

ConceptPostgreSQLMySQLSQL ServerSQLiteOracle
Date onlyDATEDATEDATETEXT / DATE affinityDATE
Time onlyTIMETIMETIMETEXT / TIME affinityDATE (with time component)
Date + timeTIMESTAMPDATETIMEDATETIME2TEXT / DATETIME affinityTIMESTAMP (deprecated) / DATE
Date + time + timezoneTIMESTAMPTZTIMESTAMPDATETIMEOFFSETTEXTTIMESTAMP WITH TIME ZONE
Auto now (current timestamp)DEFAULT NOW()DEFAULT CURRENT_TIMESTAMPDEFAULT GETDATE()DEFAULT CURRENT_TIMESTAMPDEFAULT CURRENT_TIMESTAMP

⚠️ Oracle TIMESTAMP is deprecated for new designs; use DATE for seconds precision. SQLite stores datetimes as ISO-8601 text strings by default.

✅ Boolean & Special Types

ConceptPostgreSQLMySQLSQL ServerSQLiteOracle
BooleanBOOLEANBOOLEAN / TINYINT(1)BITINTEGER (0 or 1)NUMBER(1)
UUID / GUIDUUIDBINARY(16) / CHAR(36)UNIQUEIDENTIFIERBLOB / TEXTRAW(16) / VARCHAR2(36)
JSONJSON / JSONBJSONNVARCHAR(MAX) / JSON (2016+)TEXT / JSON affinityCLOB / VARCHAR2 (with JSON constraint)
EnumCREATE TYPE ... AS ENUMENUM(...)VARCHAR + CHECKTEXT + CHECKVARCHAR2 + CHECK
ArrayINTEGER[] / TEXT[]Not nativeNot nativeNot nativeVARRAY / Nested Table

⚠️ MySQL BOOLEAN is an alias for TINYINT(1). SQLite has no native Boolean; use INTEGER 0/1. Oracle added native JSON support in 12c.

🔄 Common Migration Pitfalls

PitfallDetails
BOOLEAN → MySQLPostgreSQL BOOLEAN becomes TINYINT(1) in MySQL. Your ORM may handle this, but raw SQL migrations need care.
VARCHAR lengthMySQL VARCHAR(255) is bytes, not characters with utf8mb4. PostgreSQL VARCHAR(n) is characters.
Auto-incrementSERIAL (Postgres), AUTO_INCREMENT (MySQL), IDENTITY (SQL Server), GENERATED ALWAYS (Oracle). None are compatible.
TEXT typesSQLite TEXT is unlimited. Migrating to MySQL requires choosing TINYTEXT, TEXT, MEDIUMTEXT, or LONGTEXT.
Date/time precisionPostgreSQL TIMESTAMP has microsecond precision. SQL Server DATETIME2 has 100ns precision. Oracle DATE has second precision.
JSON storagePostgreSQL JSONB is binary and indexable. MySQL JSON is binary but with different indexing rules. SQLite stores JSON as text.

Comparing schemas across dialects?

SchemaLens compares two SQL schemas side by side and generates migration scripts in your target dialect — automatically handling type mappings, constraint differences, and breaking changes.

Compare Schemas Free →