The Legacy Obituaries

ROWID / UROWID

pre-11.2 · datatype

Survived by a workaround.

✓ certified by the mortician

In life

ROWID is the pseudocolumn and data type that gives a row's physical address in a heap table: data object number, file, block and slot. UROWID is the universal form that also covers logical rowids for index-organized tables and rowids of foreign tables. Oracle warns that a rowid can change, for example when a row moves, so storing rowids for later use yields unpredictable results.

Migrations care because rowids are used in idioms that have no target equivalent: de-duplication with MIN(ROWID), bulk-update loops that re-fetch by rowid, and application frameworks that cache rowids as row handles. SQL Server exposes no stable physical row address, and PostgreSQL's system column changes on every update, so each idiom needs a key-based rewrite.

The data type is supported and not deprecated.

Cause of departure

Not deprecated by Oracle. Listed here because Azure offers no clean equivalent.

Obituary

ROWID / UROWID, born before 11.2, served as Oracle’s physical row address exposed to SQL. It located rows and supported storage-position ordering, duplicate elimination, pagination, trigger correlation, and batching.

It departed because Azure offers no faithful equivalent: PostgreSQL’s ctid changes after updates or VACUUM FULL, while Azure SQL’s uniqueidentifier is a GUID, not a physical address. Ora2Pg’s default oid mapping can also fail during import.

It is survived by Azure Database for PostgreSQL Flexible Server, only by workaround, and Azure SQL Database, only by workaround. The contested account advises mapping no type at all: rewrite uses around primary keys, adding deliberate surrogates only for keyless tables.

Survived by

Azure Database for PostgreSQL Flexible Server workaround effort M

Applies to Oracle 11.2, 12.1, 12.2, 18c, 19c, 21c, 23ai, 26ai

PostgreSQL's ctid is a physical row locator like ROWID, but it changes on every UPDATE and after VACUUM FULL, so it is unusable as an identifier beyond a single statement. Ora2Pg maps ROWID to oid by default and warns that this fails during data import, recommending bigserial, text or uuid instead. Code should be rewritten around primary keys or an identity column.

  • Override the Ora2Pg DATA_TYPE for ROWID and UROWID to bigint (identity) or uuid.
  • Add a generated identity or uuid column to tables whose rows lacked a natural key.
  • Replace ROWID-based duplicate deletion with ctid only inside a single statement, or with ROW_NUMBER().
  • Remove ROWID columns from result sets consumed by applications.

Complications

major Ora2Pg converts ROWID and UROWID to oid by default and its documentation warns that this causes an error during data import because there is no equivalent type; it recommends overriding DATA_TYPE to bigserial, text or uuid.
major PostgreSQL's ctid identifies the physical location of a row version but changes whenever the row is updated or moved by VACUUM FULL, so the documentation says it must not be used as a row identifier; Oracle code that stored or compared ROWIDs across statements cannot use ctid.

Azure SQL Database workaround effort M

Applies to Oracle 11.2, 12.1, 12.2, 18c, 19c, 21c, 23ai, 26ai

ROWID is a physical row address exposed to SQL; SQL Server has no such value, so SSMA maps the type to uniqueidentifier and can add a ROWID column defaulting to NEWID() with a unique index, which gives applications a surrogate row identity but not the physical addressing, fast-access or duplicate-elimination tricks Oracle code used ROWID for. Queries that used ROWID to locate the current row should use the primary key instead.

  • Find ROWID and UROWID usage in code (SELECT ROWID, WHERE ROWID =, DELETE duplicates by ROWID).
  • Decide whether SSMA should generate ROWID columns (default only for tables with triggers) and whether a unique index is wanted.
  • Rewrite duplicate-removal and cursor-update patterns to use primary keys or ROW_NUMBER().
  • Drop the generated ROWID column once the application no longer references it.

Complications

major SSMA maps ROWID and UROWID to uniqueidentifier, a 16-byte GUID generated by newid(), which is not a physical row address and cannot be used to locate or order rows by storage position.
Oracle 11.2, 12.1, 12.2, 18c, 19c, 21c, 23ai, 26ai · microsoft SSMA for Oracle: Project Settings (Type Mapping)
minor SSMA's Generate ROWID column setting defaults to adding a ROWID uniqueidentifier column only to tables that have triggers (Default and Optimistic modes) and to all tables in Full mode, with a unique index on that column generated by default; the SSMA Tester requires the column on all tables.

Contested accounts

What does ROWID become: uniqueidentifier or oid?

SSMA turns ROWID into uniqueidentifier, a random 16-byte GUID. Ora2Pg turns it into oid and its own documentation warns the data import will then fail. The two converters do not merely differ; neither produces something with ROWID's meaning, because ROWID is a physical row address that no other engine exposes.

SSMA maps ROWID and UROWID to uniqueidentifier, a 16-byte GUID generated by newid(), which is not a physical row address and cannot be used to locate or order rows by storage position.

Ora2Pg converts ROWID and UROWID to oid by default and its documentation warns that this causes an error during data import because there is no equivalent type; it recommends overriding DATA_TYPE to bigserial, text or uuid.

Resolution. Do not map ROWID as a type at all. Find every use (dedupe by ROWID, MIN(ROWID) tricks, pagination, trigger correlation, ROWID-based batching) and rewrite it against the primary key or a surrogate key. Only when a table genuinely has no key add an explicit surrogate: uniqueidentifier with a unique index on Azure SQL, or bigserial or uuid on PostgreSQL, and override the converter's default so the column is created deliberately rather than by accident. (Data Types (SQL Language Reference 19c))

Notices of correction

  1. oracle Data Types (SQL Language Reference 19c) · SQL Language Reference 19c · read 2026-09-26
  2. oracle Tables and Table Clusters (Database Concepts 19c) · Database Concepts 19c, E96138-11, Sep 2025 · read 2026-09-26
  3. community Ora2Pg documentation (configuration directives) · Ora2Pg 25.0 (changelog 2025-04-20); text read from doc/Ora2Pg.pod in the GitHub repository · read 2026-09-26
  4. community PostgreSQL documentation: System columns (ctid) · PostgreSQL 18 · read 2026-09-26
  5. microsoft SSMA for Oracle: Project Settings (Type Mapping) · SSMA for Oracle, page updated 2026-08-27 · read 2026-09-26
  6. microsoft SSMA for Oracle: Project Settings (Conversion) · SSMA for Oracle, page updated 2026-08-27 · read 2026-09-26

← All notices

ROWID / UROWID — Legacy Obituaries