# SQL Data Type Mapping Table: SQL Server, Oracle, PostgreSQL and MySQL

> Source: https://netray.co/tools/sql-data-type-mapping-sql-server-oracle-postgresql-mysql
> Publisher: Netray (netray.co), AI and integration engineering for ERP and manufacturing systems.
> Section: Free Tools

## Short answer

Searchable table of equivalent data types across SQL Server, Oracle, PostgreSQL and MySQL, with the gotchas that break ERP data loads.

## Category

developer

## Erp

Multi-database

## Audience

- Data migration analyst
- ERP developer
- DBA

## Tool

**Kind:** worksheet

**Mode:** reference

**Columns:**

#### Concept

**Key:** concept

**Type:** text

#### SQL Server

**Key:** mssql

**Type:** text

#### Oracle

**Key:** oracle

**Type:** text

#### PostgreSQL

**Key:** pg

**Type:** text

#### MySQL

**Key:** mysql

**Type:** text

#### Watch out for

**Key:** gotcha

**Type:** text

**Rows:**

**Concept:** 16-bit integer

**Mssql:** smallint

**Oracle:** NUMBER(5)

**Pg:** smallint

**Mysql:** SMALLINT

**Gotcha:** Oracle has no native small integer type, NUMBER(5) is the common choice.

**Concept:** 32-bit integer

**Mssql:** int

**Oracle:** NUMBER(10)

**Pg:** integer

**Mysql:** INT

**Gotcha:** Oracle INTEGER is an alias of NUMBER(38), so precision can differ from the source.

**Concept:** 64-bit integer

**Mssql:** bigint

**Oracle:** NUMBER(19)

**Pg:** bigint

**Mysql:** BIGINT

**Gotcha:** Surrogate keys above 2 billion need bigint on every side of a join.

**Concept:** Exact decimal

**Mssql:** decimal(p,s)

**Oracle:** NUMBER(p,s)

**Pg:** numeric(p,s)

**Mysql:** DECIMAL(p,s)

**Gotcha:** Use exact types for quantities and money, never float, to avoid rounding drift.

**Concept:** Money

**Mssql:** money

**Oracle:** NUMBER(19,4)

**Pg:** numeric(19,4)

**Mysql:** DECIMAL(19,4)

**Gotcha:** SQL Server money has four decimals and rounds in intermediate division, so many teams prefer decimal.

**Concept:** Double precision float

**Mssql:** float

**Oracle:** BINARY_DOUBLE

**Pg:** double precision

**Mysql:** DOUBLE

**Gotcha:** Oracle FLOAT is a decimal-precision type, not the same as BINARY_DOUBLE.

**Concept:** Single precision float

**Mssql:** real

**Oracle:** BINARY_FLOAT

**Pg:** real

**Mysql:** FLOAT

**Gotcha:** Avoid for ERP quantities and costs.

**Concept:** Fixed length text

**Mssql:** char(n)

**Oracle:** CHAR(n)

**Pg:** char(n)

**Mysql:** CHAR(n)

**Gotcha:** Padding behaviour in comparisons differs by engine and setting.

**Concept:** Variable length text

**Mssql:** varchar(n)

**Oracle:** VARCHAR2(n)

**Pg:** varchar(n)

**Mysql:** VARCHAR(n)

**Gotcha:** Oracle length defaults to bytes unless CHAR semantics are declared, so multibyte text can overflow.

**Concept:** Unicode variable text

**Mssql:** nvarchar(n)

**Oracle:** NVARCHAR2(n)

**Pg:** varchar(n)

**Mysql:** VARCHAR(n) with utf8mb4

**Gotcha:** PostgreSQL text is Unicode already when the database encoding is UTF8.

**Concept:** Long text

**Mssql:** varchar(max) or nvarchar(max)

**Oracle:** CLOB

**Pg:** text

**Mysql:** LONGTEXT

**Gotcha:** Oracle CLOB needs special handling in many ETL tools.

**Concept:** Binary data

**Mssql:** varbinary(max)

**Oracle:** BLOB

**Pg:** bytea

**Mysql:** LONGBLOB

**Gotcha:** Attachment tables are often the slowest part of an ERP migration.

**Concept:** Date only

**Mssql:** date

**Oracle:** DATE (contains a time part)

**Pg:** date

**Mysql:** DATE

**Gotcha:** Oracle DATE stores time to the second, so comparisons with date-only values need truncating.

**Concept:** Date and time

**Mssql:** datetime2(n)

**Oracle:** TIMESTAMP(n)

**Pg:** timestamp

**Mysql:** DATETIME(n)

**Gotcha:** Legacy SQL Server datetime rounds to roughly 3 milliseconds, datetime2 does not.

**Concept:** Date and time with zone

**Mssql:** datetimeoffset

**Oracle:** TIMESTAMP WITH TIME ZONE

**Pg:** timestamptz

**Mysql:** TIMESTAMP (stored as UTC)

**Gotcha:** Decide on UTC versus local storage before loading, then convert once.

**Concept:** Time of day

**Mssql:** time

**Oracle:** No direct type, use DATE or INTERVAL DAY TO SECOND

**Pg:** time

**Mysql:** TIME

**Gotcha:** Routing and shift data often carry time-only values.

**Concept:** Boolean flag

**Mssql:** bit

**Oracle:** NUMBER(1) or CHAR(1)

**Pg:** boolean

**Mysql:** TINYINT(1) or BOOLEAN

**Gotcha:** Many ERPs use 0 and 1 or Y and N, check which one the source uses.

**Concept:** GUID

**Mssql:** uniqueidentifier

**Oracle:** RAW(16)

**Pg:** uuid

**Mysql:** CHAR(36) or BINARY(16)

**Gotcha:** Byte order of GUIDs can differ between display and storage.

**Concept:** Auto-generated key

**Mssql:** IDENTITY

**Oracle:** GENERATED AS IDENTITY (12c and later) or sequence

**Pg:** GENERATED AS IDENTITY or serial

**Mysql:** AUTO_INCREMENT

**Gotcha:** Reseed the generator after loading explicit key values.

**Concept:** XML

**Mssql:** xml

**Oracle:** XMLTYPE

**Pg:** xml

**Mysql:** No native type, use TEXT

**Gotcha:** Validate that XML round-trips without namespace changes.

**Concept:** JSON

**Mssql:** nvarchar(max) with JSON functions (native json type in recent versions)

**Oracle:** JSON (21c and later) or VARCHAR2/CLOB

**Pg:** jsonb or json

**Mysql:** JSON

**Gotcha:** jsonb reorders keys and removes duplicates.

**Concept:** Row version stamp

**Mssql:** rowversion

**Oracle:** No direct equivalent

**Pg:** No direct equivalent (system column xmin is not a stable stamp)

**Mysql:** No direct equivalent

**Gotcha:** Optimistic concurrency logic must be rewritten, not just retyped.

**Concept:** Empty string vs NULL

**Mssql:** Distinct

**Oracle:** Empty string is stored as NULL

**Pg:** Distinct

**Mysql:** Distinct

**Gotcha:** Moving into Oracle turns empty strings into NULL and can break NOT NULL columns and unique checks.

**Notes:** Mappings are common conventions, not the only valid ones. Confirm against your exact versions and any migration tool you use, and test with real row counts and boundary values.

## Content

**Intro:** ERP data migrations fail quietly when a type is mapped almost correctly. This reference lines up the common data types across SQL Server, Oracle, PostgreSQL and MySQL, with the gotcha for each.

**Sections:**

#### How to use the mapping

**Body:** List the source columns with their types from the information schema, then search each concept here to choose the target type. Record the choice in your field mapping sheet along with any length or precision change. Check the gotcha column before you accept the default your migration tool proposes, since tools usually choose the widest safe type and may not match what the target ERP expects. Validate by comparing row counts, sums of numeric columns and minimum and maximum of date columns after the load.

#### Where mappings break

**Body:** Four areas cause most problems. Oracle treats an empty string as NULL, which alters NOT NULL and unique logic. Oracle DATE carries a time part, so date joins miss rows. Length semantics differ between bytes and characters, so multibyte names such as Chinese or accented supplier names can be truncated. Finally, boolean and identity columns need logic changes rather than a type change. Build a short test set containing each of those cases and run it before the full load.

#### Precision for quantities and money

**Body:** Pick DECIMAL or NUMERIC with an explicit scale for quantities, unit costs and exchange rates. A typical choice is scale 4 for unit cost and scale 6 for exchange rates, but follow what your target ERP defines. Floating point types introduce tiny errors that break inventory-to-ledger reconciliation after a few million transactions. If the source uses money, confirm whether any computed columns divide before multiplying, because money stores four decimals and rounds at each step.

#### Common mistakes

**Body:** Teams often map every text column to the widest type, which hurts indexing and breaks tools that expect fixed lengths. Others forget collation, so case-insensitive matches in the source become case-sensitive in the target and duplicate part numbers appear. Document the collation and case rules next to the type table, and load a pilot slice of master data first.

**Cta:** If you are moving ERP data between databases and want help building the mapping and reconciliation checks, we can review your column list with you.

**Faq:**

#### Why does Oracle break my empty string columns?

**Answer:** Oracle stores a zero-length string as NULL. After migrating, NOT NULL columns can reject rows and unique checks can behave differently. Replace empty strings with an agreed placeholder or relax the constraint before loading.

#### Should I map SQL Server money to decimal?

**Answer:** Usually yes. A decimal with explicit scale, such as 19,4, keeps the same range and avoids money rounding in intermediate calculations. Whatever you choose, keep it consistent across all tables.

#### Is datetime2 the same as Oracle TIMESTAMP?

**Answer:** They are close equivalents. Both hold fractional seconds. Oracle DATE is different because it carries a time part to the second, so it is not the same as SQL Server date.

#### How do I map uniqueidentifier to Oracle?

**Answer:** RAW(16) is the usual choice. Be aware that display and byte order of GUIDs can differ between systems, so test a sample by joining on the converted value before loading.

## Search terms

sql server to oracle data type mapping, sql server to postgresql data types, oracle number to sql server, datetime2 oracle equivalent, uniqueidentifier postgresql, data type conversion erp migration, oracle varchar2 vs nvarchar, bit datatype oracle

---
Talk to an engineer: https://netray.co/contact?intent=erp_ai | Machine catalog: https://netray.co/agent/catalog.json
