GlideRecord's are one of the simplest ways to automate in ServiceNow.
What is a GlideRecord?
A GlideRecord
is a class of object that represents a table & offers a scriptable API to access records on that table
GlideRecord
is comprised of GlideElements
as well as other methods and metadata that work together to allow you to query from and write to database tables
GlideElement
is a class of object that represents a column on a table
There are two versions of GlideRecord, the client side version, and the server side version. docs
Methods available
Category | Method | Brief Description |
---|---|---|
* | getLastErrorMessage | Retrieves the last error message |
* | isValid | Determines whether the table exists or not |
* | operation | Retrieves the current operation being performed, such as insert, update, or delete |
* | setAbortAction | Sets a flag to indicate if the next database action (insert, update, delete) is to be aborted |
* | setWorkflow | Flag to run or not run other business rules |
Access | canCreate | Determines if the Access Control Rules which include the user's roles permit inserting new records in this table |
Access | canDelete | Determines if the Access Control Rules which include the user's roles permit deleting records in this table |
Access | canRead | Determines if the Access Control Rules which include the user's roles permit reading records in this table |
Access | canWrite | Determines if the Access Control Rules which include the user's roles permit editing records in this table |
Query | addEncodedQuery | Specifies one of many querys encoded |
Query | addJoinQuery | Adds a filter to return records based on a relationship in a related table |
Query | addNotNullQuery | Add's a ^fielsISNOTNULL condition |
Query | addNullQuery | Add's a ^fieldISNULL condition |
Query | addOrCondition | Add's a ^OR condition |
Query | addQuery | Specifies one of many querys |
Query | chooseWindow | Sets a range of rows to be returned by subsequent queries. If forceCount is true, getRowCount() method will return all possible records |
Query | get | Get's a single record |
Query | getEncodedQuery | Returns the query in it's encoded form |
Query | getRowCount | Gets the number of rows, not recomeneded, use GlideAggregate instead |
Query | hasNext | Determines if there are any more records in the GlideRecord |
Query | next | Moves to the next record in the GlideRecord |
Query | orderBy | Sets the order by to A-Z on the specified field |
Query | orderByDesc | Sets the order by to Z-A on the specified field |
Query | query | Runs the query against the table based on the specified filters by addQuery and addEncodedQuery |
Query | setLimit | Sets a limit on the number of results |
Query | setEncodedQuery | |
Read | addFunction | Retrieve the specified platform function in addition of the field values |
Read | getAttribute | Gets the attributes on the field in question from the dictionary |
Read | getCategory | Determines whether a category is set for a query. |
Read | getClassDisplayValue | |
Read | getDisplayName | Retrieves the name of the display field |
Read | getDisplayValue | Retrieves the display value for the current record |
Read | getElement | Retrieves the GlideElement for a specified field |
Read | getLabel | The label of the field as a String |
Read | getLink | Retrieves a link to the current record |
Read | getRecordClassName | Retrieves the class name for the current record |
Read | getTableName | Retrieves the table name associated with this GlideRecord |
Read | getValue | Retrieves the underlying value of a field |
Write | autoSysFields | Flag to update fields starting with sys_ |
Write | deleteMultiple | Deletes all records found to match the query |
Write | deleteRecord | Deletes a single record |
Write | getUniqueValue | Gets the primary key of the record, which is usually the sys_id unless otherwise specified |
Write | initialize | Sets up the GlideRecord to ignores default values for columns |
Write | insert | Insert a new record using the field values that have been set for the current record |
Write | isActionAborted | Determines whether the current database action is to be aborted. Available in Fuji patch 3 |
Write | isNewRecord | Checks if the current record is a new record that has not yet been inserted into the database |
Write | isValidField | Determines if the given field is defined in the current table |
Write | isValidRecord | Determines if current record is a valid record |
Write | newRecord | Sets up the GlideRecord to follow the default values and assigns a sys_id |
Write | setCategory | Sets the category, which determines how the query is routed to a secondary database pool. |
Write | setForceUpdate | Flag to allow a save/update when there are no changes |
Write | setNewGuid | Assigns a sys_id when called |
Write | setNewGuidValue | Sets the sys_id to the value specified |
Write | setValue | Sets the value for the specified field. |
Write | update | Updates the current GlideRecord with any changes that have been made |
Write | updateMultiple | Updates each GlideRecord in the list with any changes that have been made |
Write | updateLazy | Places update in a batch, doesn't happen immediately, code continues past it. Undocumented. |
Operators | Different Operators for GlideRecord |
*
These methods apply to query, read, write operations.
getLastErrorMessage
Retrieves the last error message.
isValid
Determines whether the table exists or not.
operation
Retrieves the current operation being performed, such as insert, update,
or delete.
setAbortAction
Sets a flag to indicate if the next database action (insert, update,
delete) is to be aborted.
setWorkflow
Enables or disables the running of business rules, script engines, and
audit.
This does not stop flows for scoped applications. Source
NOTE: This works on queries too
var incident = new GlideRecord('incident');
incident.newRecord();
incident.setValue('short_description','This is text');
incident.setWorkflow(false);//default is true
incident.insert();//returns the sys_id string of inserted record
Access
canCreate
Determines if the Access Control Rules which include the user's roles
permit inserting new records in this table.
canDelete
Determines if the Access Control Rules which include the user's roles
permit deleting records in this table.
canRead
Determines if the Access Control Rules which include the user's roles
permit reading records in this table
canWrite
Determines if the Access Control Rules which include the user's roles
permit editing records in this table.
Query
Generally most of the calls you'll make with this will be queries. See
if you find a record, find all the records, find a lack of records, then
do something else.
addEncodedQuery
// available for server, if you want to use on client, use addQuery(string)
// expects;
// string e.g. .addEncodedQuery('number=INC12345');
// returns null
var incident = new GlideRecord('incident');
incident.addEncodedQuery('number=INC12345');
incident.query();
if(incident.next()){
gs.info('found record');
gs.info(incident.getValue('sys_created_on'));
} else {
gs.info('no record found');
}
addJoinQuery
Adds a filter to return records based on a relationship in a related
table.
addNotNullQuery
I generally ignore any other method that modifies the query. These have
documentation, but I have yet to use it and find it's code more verbose.
Also this only works on server side.
addNullQuery
I generally ignore any other method that modifies the query. These have
documentation, but I have yet to use it and find it's code more verbose.
Also this only works on server side.
addOrCondition
I generally ignore any other method that modifies the query. These have
documentation, but I have yet to use it and find it's code more verbose.
Also this only works on server side. To use this in your encoded query
just put ^OR
between your query strings.
addQuery
This method is most common when coming across queries. Generally folks
with either have many addQuery methods declared, or one addEncodedQuery.
// available for both client and server
// expects;
// string e.g. .addQuery('number=INC12345');
// two strings e.g. .addQuery('number','INC12345');
// three strings e.g. .addQuery('number', '=', 'INC12345');
// returns null
var incident = new GlideRecord('incident');
incident.addQuery('number','INC12345');
incident.query();
if(incident.next()){
gs.info('found record');
gs.info(incident.getValue('sys_created_on'));
} else {
gs.info('no record found');
}
chooseWindow
Sets a range of rows to be returned by subsequent queries. If forceCount
is true, getRowCount()
method will return all possible records.
get
This method is a shortcut to get the first record found that matches the
parameters you pass in this method.
// available for both client and server
// expects one of;
// sys_id e.g. .get('asdf1234asdf1234asfd1234asdf1234');
// column, and value e.g. .get('number','INC12345');
// returns
// boolean and moves object onto the record if boolean is true
var incident = new GlideRecord('incident');
if(incident.get('number','INC12345')){//returns true if found
gs.info('found record');
gs.info(incident.getValue('sys_created_on'));
} else {
gs.info('no record found');
}
getEncodedQuery
This is really helpful if debugging code. If you're not sure why you're
getting the records you are, I generally add this to my code before my
.query()
and try the query in the GUI. This works on client and server
side code.
getRowCount
This will return the number of rows in your returned object after your
.query()
. However, this is frowned on because it has some memory
issues. I'm not sure exaclty why but generally if you need to know the
quantity of records, you should always use GlideAggregate.
getRowCount()
is available client and server side. GlideAggregate
is
only available server side.
hasNext
Determines if there are any more records in the GlideRecord.
next
Moves to the next record in the GlideRecord.
orderBy
This will return your set order ascending (a-z, 1-9) by the column name,
and is opposite of orderByDesc.
var incident = new GlideRecord('incident');
incident.addEncodedQuery('active=true');
incident.orderBy('number');
incident.query();
while(incident.next()){
gs.info('found record');
gs.info(incident.getValue('number'));
} else {
gs.info('no record found');
}
orderByDesc
This will return your set order descending (z-a, 9-1) by the columne
name, and is opposibe of orderBy.
var incident = new GlideRecord('incident');
incident.addEncodedQuery('active=true');
incident.orderByDesc('number');
incident.query();
while(incident.next()){
gs.info('found record');
gs.info(incident.getValue('number'));
} else {
gs.info('no record found');
}
query
Runs the query against the table based on the specified filters by
addQuery
and addEncodedQuery
.
setEncodedQuery
This isn't documented anywhere and I just came across this. Appears to
be a way to set the encoded query on the client. I'd avoid using this as
it isn't documented, but you can read the code here on
hi.
setLimit
This is really useful if you're running a one time script to update some
records. Run a test against one record. This works on client and server
side code.
var incident = new GlideRecord('incident');
incident.addEncodedQuery('number=INC12345');
incident.setLimit(1);
incident.query();
while(incident.next()){
gs.info('found record');
gs.info(incident.getValue('sys_created_on'));
} else {
gs.info('no record found');
}
Read
addFunction
Retrieve the specified platform function in addition of the field values
getAttribute
Gets the attributes on the field in question from the dictionary
getCategory
The setCategory and getCategory methods are available in GlideRecord for
working with query categories when routing to secondary database pools,
known as read replicas.
A read replica is a 100% copy of an instance's database (DB) that can be
only queried against with the goal to reduce load on the primary
database. It's a paid feature and requires an extra plugin that can only
be activated by ServiceNow. With setCategory you can route some
categories to the read replica, so queries for them will not go to
primary database anymore (effectively reducing load on primary
database).
getClassDisplayValue
This returns the table class display value, e.g. incident
would Return
Incident
getDisplayName
Retrieves the name of the display field
getDisplayValue
Retrieves the display value for the current record
getElement
Retrieves the GlideElement for a specified field
getLabel
The label of the field as a String
getLink
Retrieves a link to the current record
getRecordClassName
Retrieves the class name for the current record
getTableName
Retrieves the table name associated with this GlideRecord
getValue
Retrieves the underlying value of a field
Write
autoSysFields
Controls weather or not to set the sys_* fields.
var incident = new GlideRecord('incident');
incident.newRecord();
incident.setValue('short_description','This is text');
incident.autoSysFields(false);//default is true
incident.insert();//returns the sys_id string of inserted record
deleteMultiple
Generally you don't need to delete records, so this is less common to
see in use, some places you might see it used are when storing things
temporarily. Like the cart's items, those things don't stick around and
I've seen it coded to clear it out in some cases. In any case, my point
is, this is seen less often.
This is shortcut to delete a lot of records, however it's not
necessarily faster. To use this you can just specify your query, and
then invoke incident.deleteMultiple();
This is available on server only.
deleteRecord
Generally you don't need to delete records, so this is less common to
see in use, some places you might see it used are when storing things
temporarily. Like the cart's items, those things don't stick around and
I've seen it coded to clear it out in some cases. In any case, my point
is, this is seen less often.
If you have a GlideRecord object, you can specify to delete the record
like so;
incident.deleteRecord();
This is available on both server, and client, and only in the full gui,
not in mobile.
getUniqueValue
Gets the primary key of the record, which is usually the sys_id unless
otherwise specified
initialize
var incident = new GlideRecord('incident');
incident.initialize();//ignores default values for columns
incident.setValue('short_description','This is text');
incident.insert();//returns the sys_id string of inserted record
Insert
So to be absolutely clear, to insert or update a record it's nearly the
same code, except you use .insert();
or .update();
. However you may
want to use those with the following methods;
Insert a new record using the field values that have been set for the
current record.
isActionAborted
Determines whether the current database action is to be aborted.
Available in Fuji patch 3
isNewRecord
Checks if the current record is a new record that has not yet been
inserted into the database
isValidField
Determines if the given field is defined in the current table
isValidRecord
Determines if current record is a valid record
newRecord
var incident = new GlideRecord('incident');
incident.newRecord();//Creates a new GlideRecord record, sets the
// default values for the fields, and assigns a unique ID to the record.
incident.setValue('short_description','This is text');
incident.insert();//returns the sys_id string of inserted record
setCategory
The setCategory and getCategory methods are available in GlideRecord for
working with query categories when routing to secondary database pools,
known as read replicas.
A read replica is a 100% copy of an instance's database (DB) that can be
only queried against with the goal to reduce load on the primary
database. It's a paid feature and requires an extra plugin that can only
be activated by ServiceNow. With setCategory you can route some
categories to the read replica, so queries for them will not go to
primary database anymore (effectively reducing load on primary
database).
setForceUpdate
Normally if no update is detected, Servicenow will ignore the update.
With this method, it will apply the update regardless.
var incident = new GlideRecord('incident');
incident.setLimit(1);
incident.query();
if(incident.next()){
incident.setForceUpdate(true);//default is false
incident.update();//returns the sys_id string of inserted record
}
setNewGuid
This sets the guid to a value before the record is saved.
var t = new GlideRecord('task');
var tSysid = t.setNewGuid();
// some fancy script with tSysid
setNewGuidValue
This allows you to manually set your sys_id
. I used this to most
recently try to fix some broken reference, but I don't know other
reasons it may be used.
var a = new GlideRecord('ticket');
a.setNewGuidValue('14018b8cdb69a6403bddf1910f961926');
a.insert();
setValue
Sets the value for the specified field.
Update
So to be absolutely clear, to insert or update a record it's nearly the
same code, except you use .insert();
or .update();
. However you may
want to use those with the following methods;
Updates the current GlideRecord with any changes that have been made.
updateMultiple
So to be absolutely clear, to insert or update a record it's nearly the
same code, except you use .insert();
or .update();
. However you may
want to use those with the following methods;
Updates each GlideRecord in the list with any changes that have been
made.
Tim has a post about this specifically.
Here's an example of the method in use;
var staleState = 10;
var query = 'sys_updated_onRELATIVELT@dayofweek@ago@30^state=2';
var incident = new GlideRecord('incident');
incident.addQuery(query);
incident.setValue('state', staleState);
incident.updateMultiple();
updateLazy
Came up on sndevs slack. According to sources there this does;
puts the update into a batch, which means it might not happen right
away. Your code can then continue on, but side-effects like BRs and
such might not happen for a short while, because the operation doesn't
actually occur yet. It is undocumented. It has consequences and isn't
meant for casual use.
Operators
Operator label | Equivalent query operator | Example query |
---|---|---|
is not | != |
short_description!=Network storage unavailable |
and | ^ |
active=true^CallerISNOTEMPTY |
OR filter (new query) | ^NQ |
active=true^NQactive=false |
OR condition | ^OR |
short_descriptionISEMPTY^ORdescriptionISEMPTY |
before | < |
sla_due<javascript:gs.daysAgoStart(0) |
less than | < |
reassignment_count<2 |
at or before | <= |
sla_due<=javascript:gs.daysAgoEnd(0) |
less than or is | <= |
short_description<=s |
is | = |
short_description=Network storage unavailable |
after | > |
sla_due>javascript:gs.daysAgoEnd(0) |
greater than | > |
impact>2 |
at or after | >= |
sla_due>=javascript:gs.daysAgoStart(0) |
greater than or is | >= |
short_description>=s |
is anything | ANYTHING |
short_descriptionANYTHING |
between | BETWEEN |
short_descriptionBETWEENq@t |
between | BETWEEN |
impactBETWEEN1@2 |
between | BETWEEN |
sla_dueBETWEENjavascript:gs.daysAgoStart(1)@javascript:gs.daysAgoEnd(0) |
between | BETWEEN |
reassignment_countBETWEEN1@2 |
changes from | CHANGESFROM |
stateCHANGESFROM4^EQ |
changes to | CHANGESTO |
stateCHANGESTO4^EQ |
trend (after) | DATEPART |
sla_dueDATEPARTMonday@javascript:gs.datePart('dayofweek','monday','GT') |
trend (before) | DATEPART |
sla_dueDATEPARTMonday@javascript:gs.datePart('dayofweek','monday','LT') |
trend (on or after) | DATEPART |
sla_dueDATEPARTMonday@javascript:gs.datePart('dayofweek','monday','GE') |
trend (on or before) | DATEPART |
sla_dueDATEPARTMonday@javascript:gs.datePart('dayofweek','monday','LE') |
trend (on) | DATEPART |
sla_dueDATEPARTMonday@javascript:gs.datePart('dayofweek','monday','EE') |
is (dyanmic) | DYNAMIC |
caller_idDYNAMIC54635e965f510100a9ad2572f2b4774c |
is empty string | EMPTYSTRING |
caller_idEMPTYSTRING |
ends with | ENDSWITH |
short_descriptionENDSWITHoutage |
greater than field | GT_FIELD |
reassignment_countGT_FIELDreopen_count |
greater than or is field | GT_OR_EQUALS_FIELD |
reassignment_countGT_OR_EQUALS_FIELDreopen_count |
is one of | IN |
impactIN1,2 |
is empty | ISEMPTY |
short_descriptionISEMPTY |
is not empty | ISNOTEMPTY |
activeISNOTEMPTY |
is less than | LESSTHAN |
sla_dueLESSTHANactivity_due@day@before@3 |
contains | LIKE |
subcategoryLIKEem |
less than field | LT_FIELD |
reassignment_countLT_FIELDreopen_count |
less than or is field | LT_OR_EQUALS_FIELD |
reassignment_countLT_OR_EQUALS_FIELDreopen_count |
is more than | MORETHAN |
sla_dueMORETHANactivity_due@day@before@1 |
is not one of | NOT IN |
subcategoryNOT INdb2,sql server,oracle |
does not contain | NOT LIKE |
subcategoryNOT LIKEem |
not on | NOTONToday |
sla_dueNOTONToday@javascript:gs.daysAgoStart(0)@javascript:gs.daysAgoEnd(0) |
is different | NSAMEAS |
activeNSAMEASmade_sla |
on | ONToday |
sla_dueONToday@javascript:gs.daysAgoStart(0)@javascript:gs.daysAgoEnd(0) |
relative (on) | RELATIVEEE |
sla_dueRELATIVEEE@hour@ago@1 |
relative (on or after) | RELATIVEGE |
sla_dueRELATIVEGE@hour@ago@1 |
relative (after) | RELATIVEGT |
sla_dueRELATIVEGT@hour@ago@1 |
relative (on or before) | RELATIVELE |
sla_dueRELATIVELE@hour@ago@1 |
relative (before) | RELATIVELT |
sla_dueRELATIVELT@hour@ago@1 |
is same | SAMEAS |
short_descriptionSAMEASdescription |
starts with | STARTSWITH |
subcategorySTARTSWITHem |
changes | VALCHANGES |
stateVALCHANGES |