Try OpenEdge Now
skip to main content
ABL Essentials
Using Queries : Defining and using queries : Repositioning a query : Using a RowID to identify a record
 
Using a RowID to identify a record
Every record in every table of a database has a unique row identifier.
Note: The row identifier is only unique within a single storage area of a database. Since an entire database table must be allocated to a single storage area, this effectively makes the identifier unique at least within that table. A discussion of database constructs such as storage areas is beyond the scope of this book.
The identifier is called a RowID. There is both a ROWID data type that allows you to store a row identifier in a procedure variable and a ROWID function to return the identifier of a record from its record buffer.
Generally, you should consider a RowID to be a special data type without being concerned about its storage format. The RowID is (among other things) designed to be valid, not just for the OpenEdge database, but for all the different databases you can access from OpenEdge using OpenEdge DataServers, which provide access from OpenEdge to database types such as Oracle and Microsoft SQLServer.
In fact, you can't display a RowID directly in an ABL procedure. If you try to, you get an error. You can see a RowID by converting it to a CHARACTER type using the STRING function. For instance, here is a procedure that shows you the RowIDs of the rows that satisfy the sample query you've been working with:
DEFINE QUERY CustQuery FOR Customer SCROLLING.

OPEN QUERY CustQuery FOR EACH Customer WHERE Customer.State = "LA".
GET FIRST CustQuery.

DO WHILE NOT QUERY-OFF-END("CustQuery"):
  DISPLAY Customer.CustNum Customer.Name
    CURRENT-RESULT-ROW("CustQuery") LABEL "Row#"
    STRING(ROWID(Customer)) FORMAT "x(12)" LABEL "RowId"
    WITH FRAME CustFrame 15 DOWN.
  GET NEXT CustQuery.
  DOWN WITH FRAME CustFrame.
END.
The following figure shows the result.
Figure 40. Result of RowID example
The RowID is displayed as a hexadecimal value. The values you would see in your own copy of the Sports2000 database might be different from these, and certainly they would be different if you modified the data, dumped it, and reloaded it into the database, because the RowID reflects the actual storage location of the data for the record, and this is not in any way predictable or necessarily repeatable. You should never count on a RowID as a permanent identifier for a record. However, you can use a RowID if you need to relocate a record you have previously retrieved within a procedure and whose RowID you saved off. You relocate the record using the TO ROWID phrase in the REPOSITION statement.
Even in this case, you must be aware that in the event of a record deletion, it is possible that a new record could be created that has the same RowID as the record that was deleted. So, even within a single session a RowID is not an absolutely reliable pointer to a record. In addition, RowIDs are unique only within a single database storage area. Therefore, the same RowID might occur for records in different tables that happen to be in different storage areas.
With these conditions in mind, you can use the TO ROWID phrase to reposition to a record in a query. Note that the RowID is for a particular database record, not an entire query row, so you need to save off the RowID of the record buffer, not of the query name, to reuse it. And in the case of a query with a join between tables, you need to save the RowID of each record buffer in order to reposition to it later and restore each of the records in the join.
The NO-ERROR option in this phrase lets you suppress an error message if the RowID turns out to be invalid for any reason. You could then use the AVAILABLE function or the ERROR-STATUS handle (see ManagingTransactions) to determine whether the query was successfully repositioned.
There is another similar identifier in ABL called a RECID. This identifier was used in earlier versions of ABL to identify records in the same way as RowIDs do now. The RECID is essentially an integer identifier for a record, though it has its own data type. It is still supported but for several reasons (including, but not limited to, portability of code between database types that you can access with DataServers), it is strongly recommended that you use only the RowID form in new application code. ABL continues to support RECIDs mainly for backward compatibility with older applications that still use them.