Did this article resolve your question/issue?


Your feedback is appreciated.

Please tell us how we can make this article more useful. Please provide us a way to contact you, should we need clarification on the feedback provided or if you need further assistance.

Characters Remaining: 1025



Row Identifiers, RECID and ROWID Explained

« Go Back


Article Number000001685
EnvironmentProduct: Progress
Version: 8.x, 9.x
Product: OpenEdge
Version: All Supported Versions
OS: All Supported Platforms
Question/Problem Description
Row Identifiers, RECID and ROWID and how Progress can retrieve rows explained.
What is a Row Identifier?
What is the difference between a RECID and a ROWID?
How does Progress uses ROWID to retrieve records?
How does Progress uses RECID to retrieve records?
What is the default index comprised of?
Steps to Reproduce
Clarifying Information
Error Message
Defect/Enhancement Number
To understand how Progress retrieves rows, it is important to understand what row identifiers are and how they are used as part of an index.

A "rowid" is a row identifier that uniquely identifies that row (or data record) in a database.  As soon as a row is created, a row identifier is assigned to it and stays the same for the row's entire life. Even when the primary index key values are changed, the ROWID for the record remains the same. Once a row is deleted, a new row will re-use the rowid identifier. Likewise, deleting and re-creating a row can result in the row getting a new ROWID as will a dump and load.

A RECID is a 32-bit/64-bit positive integer which contains an encoding of the storage address of a record within a Progress database storage area. Recid's can be converted to integers and vice versa. A RECID is essentially a pointer to the first record fragment of the record.  OpenEdge 10.1B introduced 64-bit keys to allow for more records per storage area. For further information see Article 000044869, When does the 2 billion rowid limit per Storage Area apply?   

A ROWID is a variable-length identifier whose semantics and length vary depending on the database type. 
For OpenEdge databases, it is a hexadecimal representation of the RECID and was introduced in Progress 8.  ROWID's are not integers. They are variable length binary strings which cannot be converted to integers, except by chicanery.  ROWID's and RECID's are not interchangeable in ABL code even when they are converted to integers. For further information refer to Article 000001594, 4GL. How to convert a ROWID to a RECID and Vice Versa  

ABL Temp-tables follow the same rules as the OpenEdge database, as for the most part they use the same storage mechanisms.

For foreign databases accessed through a DataServer, the ROWID is a representation of the foreign database's rowid implementation. RECID's are too small to hold Oracle ROWID values and similar constructs in other data managers.

The distinction between RECID and ROWID only applies in ABL. In Progress/OpenEdge SQL, the value returned by the ROWID function is the one referred to here as RECID. When using the getValue() function in a stored procedure or trigger, it should be retrieved as an INTEGER into a Java Integer object. The value referred to here as ROWID is not used in Progress/OpenEdge SQL. 

In order for Progress to retrieve any row efficiently, it needs its row identifier.  These are located via the table's indexes, which will store the index key(s) and for every key a list of row identifiers for the records that contain that key field. When no index is added to a table, Progress automatically creates a default primary index in the Schema Area with the row identifier as its component.  Essentially the default index is a unique index on the row identifier. As soon as an index is added to the table’s schema, the default index is deleted.

If the row identifier is already known reading the index can be skipped, which can often be used to access a record faster.  This is done by using the RECID/ROWID function in the query's WHERE clause, example: 

For Progress databases, while a record's ROWID never changes during the lifetime of a record, the ROWID only lasts as long as the record does. If the record gets deleted the ROWID becomes available for re-use for another new record. And if that record is then re-created there is no guarantee it will get the same ROWID.  

For DataServer environments the rules depend on the foreign database implementation. The safe assumption is that over longer periods of time the ROWID can change as well.  Therefore as best practice the ROWID values can be used within a single session, but should not be stored beyond that session, The first read of a record should always be by it's key fields in the data to fetch the current ROWID for the session.

With the implementation of table partitioning in OpenEdge 11.4:

RECID can no longer be used to uniquely reference data in a partitioned table as they do not contain a partition-Id component and always pertain to partition 0. 
The existing ROWID information plus the table number is no longer sufficient to uniquely identify a specific record in the database.  
Uniqueness is obtained by also including the partition id associated with the record.  
The internal format of a ROWID has been extended to include the partition information.  
The information associated with a RECID only contains the encoded block and record within block information.
An example is provided in Article: 000047328, How to recover records in a damaged partitioned table     

Implementation of the ROWID representation may be different in future releases, also depending on database type. The changes would not affect functionality but would be aimed at improving performance and scalability
Last Modified Date12/4/2019 7:05 PM