← Script library

Script Includes

Record Query Utility

Efficient GlideRecord query patterns with built-in best practices, error handling, and common operations.

JavaScript
var QueryUtils = Class.create();
QueryUtils.prototype = {

  /**
   * Get single record by sys_id with error handling
   * @param {string} table - Table name
   * @param {string} sysId - Record sys_id
   * @returns {GlideRecord|null} Record or null if not found
   */
  getById: function(table, sysId) {
    if (!table || !sysId) {
      gs.warn('QueryUtils.getById: Missing table or sys_id');
      return null;
    }

    var gr = new GlideRecord(table);
    if (gr.get(sysId)) {
      return gr;
    }

    return null;
  },

  /**
   * Get records with query string
   * @param {string} table - Table name
   * @param {string} query - Encoded query string
   * @param {number} limit - Maximum results (default: no limit)
   * @returns {array} Array of GlideRecord objects
   */
  getRecords: function(table, query, limit) {
    var records = [];

    var gr = new GlideRecord(table);
    if (query) {
      gr.addEncodedQuery(query);
    }

    if (limit) {
      gr.setLimit(limit);
    }

    gr.query();

    while (gr.next()) {
      // Push a copy of the record
      var record = new GlideRecord(table);
      record.get(gr.sys_id);
      records.push(record);
    }

    return records;
  },

  /**
   * Check if record exists
   * @param {string} table - Table name
   * @param {string} field - Field name
   * @param {string} value - Field value
   * @returns {boolean} True if record exists
   */
  exists: function(table, field, value) {
    var gr = new GlideRecord(table);
    gr.addQuery(field, value);
    gr.query();

    return gr.hasNext();
  },

  /**
   * Count records matching query
   * @param {string} table - Table name
   * @param {string} query - Encoded query string (optional)
   * @returns {number} Count of matching records
   */
  count: function(table, query) {
    var ga = new GlideAggregate(table);

    if (query) {
      ga.addEncodedQuery(query);
    }

    ga.addAggregate('COUNT');
    ga.query();

    if (ga.next()) {
      return parseInt(ga.getAggregate('COUNT'));
    }

    return 0;
  },

  /**
   * Get distinct values for a field
   * @param {string} table - Table name
   * @param {string} field - Field name
   * @param {string} query - Optional encoded query
   * @returns {array} Array of distinct values
   */
  getDistinctValues: function(table, field, query) {
    var values = [];

    var ga = new GlideAggregate(table);

    if (query) {
      ga.addEncodedQuery(query);
    }

    ga.groupBy(field);
    ga.query();

    while (ga.next()) {
      var value = ga.getValue(field);
      if (value) {
        values.push(value);
      }
    }

    return values;
  },

  /**
   * Batch update records
   * @param {string} table - Table name
   * @param {string} query - Encoded query string
   * @param {object} updates - Object with field: value pairs
   * @param {boolean} skipWorkflow - Skip business rules (default: false)
   * @returns {number} Number of updated records
   */
  batchUpdate: function(table, query, updates, skipWorkflow) {
    var count = 0;

    var gr = new GlideRecord(table);
    if (query) {
      gr.addEncodedQuery(query);
    }

    gr.query();

    while (gr.next()) {
      // Apply updates
      for (var field in updates) {
        if (updates.hasOwnProperty(field)) {
          gr.setValue(field, updates[field]);
        }
      }

      // Set workflow flag if requested
      if (skipWorkflow) {
        gr.setWorkflow(false);
      }

      gr.update();
      count++;
    }

    gs.info('QueryUtils.batchUpdate: Updated ' + count + ' records in ' + table);
    return count;
  },

  /**
   * Delete records matching query
   * @param {string} table - Table name
   * @param {string} query - Encoded query string
   * @param {boolean} skipWorkflow - Skip business rules (default: false)
   * @returns {number} Number of deleted records
   */
  batchDelete: function(table, query, skipWorkflow) {
    var count = 0;

    var gr = new GlideRecord(table);
    if (query) {
      gr.addEncodedQuery(query);
    }

    gr.query();

    while (gr.next()) {
      if (skipWorkflow) {
        gr.setWorkflow(false);
      }

      gr.deleteRecord();
      count++;
    }

    gs.info('QueryUtils.batchDelete: Deleted ' + count + ' records from ' + table);
    return count;
  },

  /**
   * Copy record to another table or same table
   * @param {string} sourceTable - Source table name
   * @param {string} sourceSysId - Source record sys_id
   * @param {string} targetTable - Target table name (can be same as source)
   * @param {array} excludeFields - Fields to exclude from copy
   * @returns {string|null} New record sys_id or null if failed
   */
  copyRecord: function(sourceTable, sourceSysId, targetTable, excludeFields) {
    excludeFields = excludeFields || ['sys_id', 'sys_created_on', 'sys_created_by', 
                                       'sys_updated_on', 'sys_updated_by'];

    var source = new GlideRecord(sourceTable);
    if (!source.get(sourceSysId)) {
      gs.warn('QueryUtils.copyRecord: Source record not found');
      return null;
    }

    var target = new GlideRecord(targetTable);
    target.initialize();

    // Copy all fields except excluded ones
    var fieldNames = source.getFields();
    for (var i = 0; i < fieldNames.size(); i++) {
      var fieldName = fieldNames.get(i).getName();

      if (excludeFields.indexOf(fieldName) === -1) {
        target.setValue(fieldName, source.getValue(fieldName));
      }
    }

    var newSysId = target.insert();

    if (newSysId) {
      gs.info('QueryUtils.copyRecord: Created new record ' + newSysId);
      return newSysId;
    }

    return null;
  },

  /**
   * Get records with pagination
   * @param {string} table - Table name
   * @param {string} query - Encoded query string
   * @param {number} page - Page number (1-indexed)
   * @param {number} pageSize - Records per page
   * @returns {object} {records: array, total: number, page: number, totalPages: number}
   */
  getPaginated: function(table, query, page, pageSize) {
    page = page || 1;
    pageSize = pageSize || 10;

    // Get total count
    var total = this.count(table, query);
    var totalPages = Math.ceil(total / pageSize);

    // Get paginated results
    var gr = new GlideRecord(table);
    if (query) {
      gr.addEncodedQuery(query);
    }

    // Calculate offset
    var offset = (page - 1) * pageSize;
    gr.chooseWindow(offset, offset + pageSize);
    gr.query();

    var records = [];
    while (gr.next()) {
      var record = new GlideRecord(table);
      record.get(gr.sys_id);
      records.push(record);
    }

    return {
      records: records,
      total: total,
      page: page,
      pageSize: pageSize,
      totalPages: totalPages
    };
  },

  type: 'QueryUtils'
};

How to use it

1. Create a new Script Include named 'QueryUtils' 2. Leave 'Client callable' unchecked 3. Copy the code above 4. Use in Business Rules or Background Scripts: var query = new QueryUtils(); var incident = query.getById('incident', incidentId); var count = query.count('incident', 'active=true^priority=1'); query.batchUpdate('task', 'active=false', {state: 'closed'});

Adapt the table names, fields, and conditions to your instance. Test the behavior in a development environment before using it in production.