What It Does
The query() method executes the SQL SELECT statement built from your GlideRecord conditions, filters, and ordering. ServiceNow converts your addQuery() conditions into a SQL WHERE clause, applies ACL restrictions, and executes the query against the database. The method doesn't return the results directly — instead, it loads them into the GlideRecord object's internal cursor for iteration.
Under the hood, ServiceNow generates SQL with automatic JOINs for dot-walked fields, applies row-level security through ACLs, and handles database-specific optimizations. The platform also injects additional WHERE conditions for domain separation, update sets context, and security constraints. The query executes immediately when you call this method — there's no lazy loading.
The method returns void — it doesn't give you a count, boolean, or result set. Success or failure is determined by calling hasNext() or attempting next() after the query executes. If no records match your conditions, the GlideRecord cursor remains empty but no error occurs.
A critical edge case: in before Business Rules, query() becomes a no-op because the current record is already loaded into the GlideRecord object. The platform ignores any conditions you've added and the cursor contains only the triggering record. This behavior catches many developers off-guard when they try to query related records using the same GlideRecord variable.
The method works in close partnership with next() for iteration, getRowCount() for counting results, and hasNext() for checking if results exist. Without calling query() first, these methods either return incorrect values or throw errors.
When to Use This
Use query() when you need to retrieve multiple records matching specific criteria, whether for iteration, counting, or checking existence. This is the standard pattern for most database operations in ServiceNow server-side scripts. The method is essential for Business Rules that query related records, Script Includes that process datasets, and Scheduled Jobs that operate on filtered record sets.
Don't use query() when you need a single record by sys_id — use get() instead. For simple existence checks, getRowCount() after query() is more performant than iteration. Avoid calling query() inside loops — it's expensive and usually indicates a design problem that should use aggregate queries or different data access patterns.
Common misuse includes calling query() multiple times on the same GlideRecord object, which resets the cursor and wastes database resources. Another anti-pattern is forgetting to call it entirely, then wondering why next() doesn't work or returns unexpected results.
Return Value
The method returns void (undefined in JavaScript), regardless of whether the query succeeds, fails, or finds zero records. This design forces you to check results through other GlideRecord methods rather than assuming success from a return value. The actual query results populate the internal cursor structure of the GlideRecord object.
When no records match your conditions, the method still returns void but leaves the cursor empty. Database errors or permission violations also return void — you must use isValid() or hasNext() to distinguish between these scenarios.
Enjoying this? Get one deep-dive per week.
Join 1,000+ ServiceNow pros — scripts, GlideRecord patterns, Flow Designer techniques, and career moves. Free.
Platform Behavior & Side Effects
- Automatically applies ACL read restrictions — records you can't read won't appear in results
- Does not trigger Business Rules or other server-side events — it's read-only
- Performance scales with result set size — large queries can impact response time
- Results are not cached — subsequent queries execute fresh database calls
- In before Business Rules, completely ignores your conditions and loads only the current record
- Respects domain separation and security constraints automatically
- Creates database connection overhead — avoid excessive query() calls in tight loops