Record phrase
- Last Updated: February 24, 2026
- 16 minute read
- OpenEdge
- Version 12.2
- Documentation
Identifies the record or records you want to verify using the
CAN-FIND function, retrieve with a FIND statement, query
with a FOR statement or OPEN QUERY statement, or preselect
in a DO or REPEAT block.
The Record phrase syntax describes three kinds of information:
- Qualifies the record(s) to access in the table
- Specifies the index to use when locating records
- Defines the type of record lock to apply when the records are read
Syntax
|
OUTER-JOIN, OF, WHERE,
USE-INDEX, TABLE-SCAN, and USING
options in any order. You cannot use field-list in an
OPEN QUERY statement. You cannot use OUTER-JOIN or
EXCLUSIVE-LOCK in a CAN-FIND function.- record
-
The name of a database table, a temp-table that you named in a
DEFINE TEMP-TABLEstatement, or a buffer that you named in aDEFINE BUFFERstatement. If record is the name of a table, record actually refers to the default buffer of the specified database table or temp-table. Also, the default buffer for a database table is always scoped to the main external procedure or class definition block even if you reference the default buffer in a sub-block, such as an internal procedure or method of a class.To access a record in a table defined for multiple databases, you must qualify the record's table name with the database name. Use this syntax to refer to a record in a table for a specific database:
dbname.tablenameYou do not have to qualify the reference if record is the name of a defined buffer.
- field-list
- Specifies a list of fields to include or exclude when you retrieve
records.
Field lists allow you to retrieve only specified fields rather than all the fields of a record. They can improve performance over a network by enabling more records to fit into a single network message. Field lists can be added to a
FOR,DO PRESELECT, orREPEAT PRESELECTstatement. They are also available for queries using theDEFINE QUERYstatement, except when the query is against a temp-table. The following is the syntax for field-list:{ FIELDS [ ( [field...] ) ] | EXCEPT [ ( [field...] ) ] }TheFIELDSoption specifies the fields you want to include in a record retrieval, and theEXCEPToption specifies the fields that you want to exclude from a record retrieval. The field parameter is the name of a single field in the specified table. If field is an array reference, the whole array is retrieved. SpecifyingFIELDSwith no field references retrieves no fields. However theROWIDvalue for a specified record is available using theROWIDfunction. SpecifyingEXCEPTwith no field references or specifying record without a field-list causes the AVM to retrieve a complete record.Note:Field lists should be used with caution because they can cause unexpected run-time errors. For example, it is possible that you did not include a field that is required by a new or revised subroutine or trigger. The result can be a run-time error that may be difficult to debug. A workaround is to use either the Field List Disable (-fldisable) or the Reread Fields (-rereadfields) client session startup parameter. This will allow your application to run (although more slowly) until the application can be fixed.
Note the difference between
-fldisableand-rereadfields. The Field List Disable (-fldisable) parameter causes the AVM to ignore all field lists and to fetch the entire record for every query. The Reread Fields (-rereadfields) parameter causes the AVM to fetch the record with the specified fields, but then re-fetch the entire record if an ABL statement tries to reference a field that is not there. Also note that when the re-fetch happens, anyFINDtrigger is not run again.This statement retrieves only the
NameandBalancefields of theCustomertable:FOR EACH customer FIELDS (name balance): DISPLAY name balance.This statement retrieves all fields of the
Customertable except theNameandBalancefields:FOR EACH Customer EXCEPT (Name Balance): DISPLAY Customer EXCEPT Customer.Name Customer.Balance.When you specify a field list, the AVM might retrieve additional fields or the complete record depending on the type of retrieval operation and the DataServer that provides the record. Thus, the AVM:
- Retrieves any additional fields required by the client to complete the record selection.
- Retrieves a complete record when the record is fetched with
EXCLUSIVE-LOCK. This ensures proper operation of updates and the local before-image (BI) file. For information on the local BI file, see Manage the OpenEdge Database. - Retrieves a complete record for DataServers that do not support
SHARE-LOCK. For more information, see the appropriate DataServer guides (Use the Microsoft SQL Data Server and Use the Oracle Data Server).
Note: Always specify fields that you plan to reference in the field list. Only those extra fields that the client requires for record selection are added to the specified field list. The AVM distributes record selection between the client and server depending on a number of factors that change with each OpenEdge release. Therefore, never rely on fields that you did not specify but which the AVM fetches for its own needs; they might not always be available. There is no additional cost to specify a field in the list that you otherwise expect the AVM to provide.This statement retrieves the
Customer.CustNumfield in addition to those specified in the field lists because it is required to satisfy the inner join between theCustomerandOrdertables:FOR EACH Customer FIELDS(Name) NO-LOCK, EACH Order FIELDS(OrderNum SalesRep) OF Customer NO-LOCK: DISPLAY Customer.Name Customer.CustNum Order.OrderNum Order.SalesRep.However, do not rely on the AVM to always provide such extra fields. For reliability, add the
CustNumfield to theCustomerfield list as follows:FOR EACH Customer FIELDS(Name CustNum) NO-LOCK, EACH Order FIELDS(OrderNum SalesRep) OF Customer NO-LOCK: DISPLAY Customer.Name Customer.CustNum Order.OrderNum Order.SalesRep. - constant
- The value of a single component, unique, primary index for the record
you want. This option is not supported for the
OPEN QUERYstatement:FIND Customer 1.The AVM converts this
FINDstatement with the constant option of 1 to the following statement:FIND Customer NO-LOCK WHERE Customer.CustNum = 1.The
CustNumfield is the only component of the primary index of theCustomertable.If you use the constant option, you can use it only once in a single Record phrase, and it must precede any other options in the Record phrase.
- [ LEFT ] OUTER-JOIN
- Specifies a left outer join between record and the table (or join) specified by the previous Record phrase(s)
of an
OPEN QUERYstatement. A left outer join combines and returns data from the specified tables in two ways. First, the records selected for the table (or join) on the left side combine with each record selected using theOForWHEREoptions from the table on the right (record). Second, the records selected for the table (or join) on the left side combine with the Unknown value (?) for the fields from the table on the right (record) for which no records are selected using theOForWHEREoptions. The join is ordered according to the given sort criteria starting with the left-most table in the query.Note: If you specify theOUTER-JOINoption, you must also specify theOUTER-JOINoption in all succeeding Record phrases of the query to obtain a left outer join. That is, for multiple Record phrases, all joins in the query following your first left outer join must also be left outer joins. Otherwise, the result is an inner join for all records up to the last inner join in the query. For more information, see Specifying the type of join in OpenEdge Programming Interfaces.The
OUTER-JOINoption is supported only in theOPEN QUERYstatement and in Record phrases specified after the first Record phrase in theOPEN QUERYstatement. TheLEFTkeyword is optional withOUTER-JOIN. If you specifyOUTER-JOIN, you must also specify theOFoption,WHEREoption, or any combination of theOFandWHEREoptions. These options are required to select record (the right-most table) for the specified left outer join. For example:OPEN QUERY q1 PRESELECT EACH Customer, FIRST Order OUTER-JOIN OF Customer WHERE Order.OrderNum < 50 FIRST OrderLine OUTER-JOIN OF Order WHERE OrderLine.ItemNum < 15.This query specifies a left outer join between
CustomerandOrder, and also between that join andOrderLine. Thus, for eachCustomerrecord that has no orders or has no orders with anOrderNumless than 50, the query returns theCustomerfields and?for all fields of theOrderandOrderLinetables. In addition, if there are noOrderLinerecords withItemNumless than 15 for any selectedCustomerandOrder, the query returns?for all fields ofOrderLine. Otherwise, it returns eachCustomerrecord along with its first selectedOrderrecord andOrderLinerecord.In all statements where multiple Record phrases are allowed (including
DO,FOR,OPEN QUERY, andREPEATstatements), the default join (without theOUTER-JOINoption) is an inner join between record and the table (or join) specified by the previous Record phrase(s). An inner join returns the records selected for the table (or join) on the left side combined with each selected record from the table on the right (record). For an inner join, no records are returned for the table (or join) on the left for which no record is selected from the table on the right (record).The following query specifies an inner join between
CustomerandOrder, and also between that join andOrderLine. Thus, this query only returnsCustomerrecords that have at least oneOrderwithOrderNumless than 50 that also have at least oneOrderLinewithItemNumless than 15, and it returns just the first suchOrderandOrderLinefor eachCustomerrecord.OPEN QUERY q1 PRESELECT EACH Customer, FIRST Order OUTER-JOIN OF Customer WHERE Order.OrderNum < 50 FIRST OrderLine OF Order WHERE OrderLine.ItemNum < 15.Note: If you specify a Record phrase as an inner join, the current Record phrase and all preceding Record phrases in the query participate in contiguous inner joins, even if prior Record phrases specify theOUTER-JOINoption. Thus, for multiple Record phrases, all joins in the query up to the right-most inner join result in contiguous inner joins.For more information on joins in ABL, see Joining tables in OpenEdge Programming Interfaces.
- OF table
- OF table is a shorthand notation,
and is converted to an expression in the
WHEREclause.OFrelates record to one other table specified by a table or buffer name (table). The relationship is based on common field names between record and table that also participate in a unique index for either record or table. When you useOFand the unique index is multi-field, all fields in the index participate in the match criteria. A reference to table must appear in a prior joined Record phrase in the same statement, or remain in scope from a prior record reading statement, such as aFINDstatement.Note: For theOFkeyword to properly detect a relationship between two tables, only one such relationship is allowed.Note: The compiler chooses an index based on the criteria specified with theWHERE,USING,OF, or constant options, ifUSE-INDEXwas not specified. Note that since theOFoption is converted to an expression in theWHEREclause, that expression is evaluated along with the other expressions in theWHEREclause, if any.In this example, the
OFoption relates theOrdertable to theCustomertable; thus the AVM selects theCustomerrecord related to theOrderrecord currently in use. The AVM converts theFINDstatement with theOFoption to aFINDstatement with theWHEREoption.PROMPT-FOR Order.OrderNum. FIND Order NO-LOCK USING Order.OrderNum. DISPLAY Order. FIND Customer OF Order NO-LOCK. DISPLAY customer.You can use
WHEREto access related tables, whether or not the field names of the field or fields that relate the tables have the same name. For example:FIND Customer NO-LOCK WHERE Customer.CustNum = Order.CustNum. - WHERE expression
- Qualifies the records you want to access. The expression is a constant, field name, variable name, or
expression whose value you want to use to select records. You can use the
WHEREkeyword even if you do not supply an expression. For example:FOR EACH Customer NO-LOCK WHERE {*}The
WHEREclause may not work the same way against a DataServer as it does against the OpenEdge database. Refer to the appropriate DataServer Guide (Use the Microsoft SQL Data Server or Use the Oracle Data Server), for additional information on how this feature will perform.Note: You cannot reference an OpenEdge BLOB or CLOB field in aWHEREclause. However, in OpenEdge DataServer for MS SQL Server, a non-legacy BLOB or CLOB server data type can be mapped to the OpenEdge CHARACTER data type in aWHEREclause operand as long as the total size of the resolvedWHEREclause (which might include the CHARACTER-mapped value) does not exceed 30000 bytes.Note: Use the -noroutineinwhereparameter to force the compiler to raise an error, if theWHEREexpression contains a user-defined function, a class method, or a class property, which implements theGETmethod using ABL statements.In an
OPEN QUERYstatement orFORstatement, theWHEREclause can use theCONTAINSoperator to reference a field with a word index. This is the syntax for theCONTAINSoperator:field CONTAINS search-expressionIn this syntax, field represents a field in which a word index has been defined. The search-expression specifies one or more words to search for. It must evaluate to a string with this syntax:
"word[[ & | | | ! | ^ ]word]..."Each word is a word to search for. The ampersand (
&) represents a logicalAND; the vertical line (|), exclamation point (!), or caret (^) represent a logicalOR. You can use an asterisk (*) as a wildcard, but only at the end of a word. Using an asterisk anywhere else in a word raises an error.Here is an example using the
CONTAINSclause:FOR EACH Item NO-LOCK WHERE Item.CatDescription CONTAINS "ski": DISPLAY Item.ItemName Item.CatDescription VIEW-AS EDITOR SIZE 60 BY 15. END.You can use parenthesis to establish precedence in the search string. For example, the following expression returns a subset of the catalog descriptions containing
"ski":WHERE Item.CatDescription CONTAINS "ski & (gog* ! pol*)"The
CONTAINSoperator must be used in an expression on its own, and not in a subexpression (for example, in an IF function).You cannot apply the
NOToperator to aCONTAINSexpression.Note: TheCONTAINSoption is not allowed in aFINDstatement. If the session is started with the Version 6 Query (-v6q) parameter, theCONTAINSoption is also not allowed in aFORstatement.Note: For more information, see Compile, make available, and apply the UTF-8 word-break rules to a database in Internationalize ABL Applications. - TENANT-WHERE expression [ SKIP-GROUP-DUPLICATES ]
- Allows a super tenant to specify which tenants are to be included in
a query, where expression is a relational operation,
or a logical combination of relational operations, that test for a character or integer
expressions that correspond to a tenant name or tenant ID, respectively. In order to use
the
TENANT-WHEREfunctionality at run time, you must be a super tenant, not a regular tenant.You can only use the
TENANT-WHEREoption in theFOR EACHstatement or option of a query. If you use aTENANT-WHEREin a join, you can have only one such option at one level of the join.Note: This option does not change the effective tenancy for a super tenant. For more information on effective tenancy, see the entry for the SET-EFFECTIVE-TENANT function.The
SKIP-GROUP-DUPLICATESoption allows you to skip duplicate data for a tenant group.If a query has been coded with a
TENANT-WHEREoption, and compiled, but is run by a regular tenant, the AVM raises a run-time error.Note that any use of the
TENANT-IDorTENANT-NAMEfunctions in aTENANT-WHEREexpression must not specify the optional database parameter, as the compiler assumes the database is the same as for the query in which theTENANT-WHEREoption is specified.For more information on this option, and examples, see the section on Multi-tenant ABL in OpenEdge Programming Interfaces.
- USE-INDEX index
- Identifies the index you want to use while selecting records. If you
do not use this option, the AVM selects an index to use based on the criteria specified
with the
WHERE,USING,OF, or constant options. - TABLE-SCAN
- You can use the
TABLE-SCANoption as an alternative to theUSE-INDEXkeyword inFOR EACHstatements.TABLE-SCANprovides the most efficient access method when retrieving all rows of a temp-table or a database table in a Type II Storage area.TABLE-SCANreturns these rows without using an index. When theTABLE-SCANkeyword is used, the AVM only accesses the record block instead of both record and index blocks.FOR EACH record ...[ USE-INDEX index | TABLE-SCAN ]For a table in a Type I storage, the AVM uses the default index to perform the scan instead of
TABLE-SCAN. If the QryInfo log entry is set, the AVM logs message if theTABLE-SCANkeyword is used on a Type I Storage area.Here is an example using the
TABLE-SCANkeyword:FOR EACH mytable TABLE-SCAN: totalCost = totalCost + mytable.cost END.Here mytable is in a Type II Storage area. The AVM uses
TABLE-SCANinstead ofWHOLE-INDEXto access the record blocks. The AVM accesses both primary index and record blocks, if theWHOLE-INDEXkeyword is used.For more information, see the Search without index section in Use ABL Database Triggers and Indexes.
- USING [ FRAME frame ] field [ AND [ FRAME frame ] field] . . .
- One or more names of fields for selecting records. You must have
previously entered each field you name in this option, usually with a
PROMPT-FORstatement. The field must be viewed as a fill-in or text widget.The
USINGoption translates into an equivalentWHEREoption:PROMPT-FOR Customer.CustNum. FIND Customer NO-LOCK USING Customer.CustNum.This
FINDstatement is the same as this statement:FIND Customer NO-LOCK WHERE Customer.CustNum = INPUT Customer.CustNum.The
CustNumfield is a non-abbreviated index. However, if theNamefield is an abbreviated index of theCustomertable, the AVM converts theFINDstatement with theUSINGoption. For example:PROMPT-FOR Customer.Name. FIND Customer NO-LOCK USING Customer.Name.The following statement is a result of the previous one:
FIND Customer NO-LOCK WHERE Customer.Name BEGINS INPUT Customer.Name. - SHARE-LOCK
- Tells the AVM to put a
SHARE-LOCKon records as they are read. Another user can read a record that is share locked, but cannot update it. By default, the AVM puts aSHARE-LOCKon a record when it is read (unless it uses aCAN-FINDfunction), and automatically puts anEXCLUSIVE-LOCKon a record when it is modified (unless the record is alreadyEXCLUSIVE-LOCKed).In a
CAN-FINDfunction,NO-LOCKis the default. Also,CAN-FINDcannot useEXCLUSIVE-LOCK.If you use the
SHARE-LOCKoption and the AVM tries to read a record that isEXCLUSIVE-LOCKed by another user, the AVM waits to read the record until theEXCLUSIVE-LOCKis released. The AVM displays a message to the user of that procedure, identifying the table that is in use, the user ID of the user, and the tty of the terminal using the table.If you are using a record from a work table, the AVM disregards the
SHARE-LOCKoption. - EXCLUSIVE-LOCK
- Tells the AVM to put an
EXCLUSIVE-LOCKon records as they are read. Other users cannot read or update a record that isEXCLUSIVE-LOCKed, except by using theNO-LOCKoption. They can access that record only when theEXCLUSIVE-LOCKis released. The AVM automatically puts aSHARE-LOCKon a record when it is read and automatically puts anEXCLUSIVE-LOCKon a record when it is updated.If a record is read specifying
EXCLUSIVE-LOCK, or if a lock is automatically changed toEXCLUSIVE-LOCKby an update, user's read or update will wait if any other userSHARE-LOCKed orEXCLUSIVE-LOCKed the record.When a procedure tries to use a record that is
EXCLUSIVE-LOCKed by another user, the AVM displays a message identifying the table that is in use, the user ID of the user, and the tty of the terminal using the table.If you are using a record from a work table, the AVM disregards the
EXCLUSIVE-LOCKoption. Also,CAN-FINDcannot use theEXCLUSIVE-LOCKoption.Specifying
EXCLUSIVE-LOCKcauses the AVM to retrieve complete records, even when the record is specified with field-list. - NO-LOCK
- Tells the AVM to put no locks on records as they are read, and to
read a record even if another user has it
EXCLUSIVE-LOCKed.Another user can read and update a record that is not locked. By default, the AVM puts a
SHARE-LOCKon a record when it is read (unless it uses aCAN-FINDfunction, which defaults toNO-LOCK), and automatically puts anEXCLUSIVE-LOCKon a record when it is updated (unless the record is alreadyEXCLUSIVE-LOCKed). A record that has been readNO-LOCKmust be reread before it can be updated.DEFINE VARIABLE rid AS ROWID NO-UNDO. rid = ROWID(customer). FIND Customer EXCLUSIVE-LOCK WHERE ROWID(Customer) = rid.If a procedure finds a record and it places it in a buffer using
NO-LOCKand you then re-find that record usingNO-LOCK, the AVM does not reread the record. Instead, it uses the copy of the record that is already stored in the buffer. To make sure the AVM gets a fresh copy of the record from the database, you must release allNO-LOCKbuffers referencing the record or retrieve the record withEXCLUSIVE-LOCK. Note that you can use the Reread Nolock (-rereadnolock) startup parameter to change this default behavior.When you read records with
NO-LOCK, you have no guarantee of the overall consistency of those records because another user might be in the process of changing them. When values are assigned to indexed fields for a newly created record or are modified in an existing record, the index is immediately updated to reflect the change. However the copy of the data record in the buffers used by the database server might not be updated until later in the transaction. For example, the following procedure might display aCustNumof 0 if another user's active transaction has created a record and assigned a value to the indexed fieldCustNumthat is greater than 100:FOR EACH Customer NO-LOCK WHERE Customer.CustNum > 100 DISPLAY Customer.CustNum. END.If you are using a record from a work table, the AVM disregards the
NO-LOCKoption. - NO-PREFETCH
- Specifies that only one record is sent across the network at a time. If you specify field-list, only the specified fields and any additional fields required for record selection are sent. If you do not specify this option, the AVM can send more than one record from the server to the client in each network packet.
Examples
In the r-recph.p procedure, there
are two Record phrases that make an inner join between the Customer and
Order tables.
r-recph.p
|
Using these Record phrases, the FOR EACH block reads a
Customer record only if it has a CreditLimit value greater than 50000 and at least one Order
record associated with it.
r-recph2.p
|
In the r-recph2.p procedure, there is one Record phrase:
|
Using the zip index named country-post rather than the CustNum index (the primary index for the
Customer table), the FIND statement reads only those
Customer records that have a Name that
begins with an s. The FIND also places an
EXCLUSIVE-LOCK on each record as it is read. This lock is released at the
end of the REPEAT block.
In the output of this procedure, all the Customer names
begin with s and the customers are displayed in order by country and then
postal code.
Notes
- Specifying a field list (field-list) for record can increase the performance of remote (network) record retrieval substantially over specifying record alone.
- You cannot specify field lists or joins in a
FINDstatement, or specify field lists in anOPEN QUERYstatement. - You cannot reference a BLOB or CLOB field in a
WHEREclause. - Temp-tables and work tables can be used in join conditions specified
with the
OFoption as long as theOFoption requirements identified earlier in this section have been satisfied. - Do not compare case-sensitive data with case-insensitive data in a
WHEREexpression. The AVM both cannot determine the results and does not raise the ERROR condition if you specify data with mixed case sensitivity in selection criteria because:- Mixed case sensitivity in selection criteria is handled differently by different DataServers.
- Mixed case-sensitivity results for the same DataServer can be different depending on whether the query is resolved on the client or the server.
- Some national languages do not support the concept of case sensitivity.
Thus, such queries cannot be reliably resolved in any way.
- For SpeedScript, the only invalid option is
USING FRAME. - In a class definition, ABL treats the default buffer of a database table that you reference as an instance data member of the class. Therefore, you cannot access a default database buffer from a static member of a class, such as a static query or method; instead, you can define an alternate static buffer data member to access records of the database table from another static class member.
- You can reference any of the following functions and attributes in the
expression of a
WHEREorTENANT-WHEREoption as long as the buffer specified for the function or attribute is not the same as the buffer of the query orFOR EACHstatement:
See also
DEFINE QUERY statement, DO statement, FIND statement, FOR statement, OPEN QUERY statement, REPEAT statement