Locate any record in any table, by sys_id in ServiceNow

Dozens of times, I've seen hard-coded sys_ids in scripts or system properties, and wanted to know what record they correspond to. Unfortunately, there isn't really a good way to do this without knowing what table the sys_id is in!
The global search box only supports searching by sys_id on tables for which that is specifically enabled, so the only solution for this has often been to scour script after script, digging down until I find where the sys_id is actually used, and try to decipher what table it corresponds to. Well, today I decided - "Enough is enough" - and I wrote a script to check each table for me. I was surprised at the ease with which I was able to accomplish my goal, as well as the speed and simplicity of the script.

Skip to the end of this article for the part where I give you a way to import this directly into your instance, for free!

So without further adieu, here is my code:

function findAnywhere(sysid, html) {
    if (html !== true && html !== 'true') { html = false; }
    var check;
    var tableName;
    var url = gs.getProperty('glide.servlet.uri');
    var table = new GlideRecord('sys_db_object');
    //Make sure we're not looking at a ts (text search) table.
    table.addEncodedQuery('sys_update_nameISNOTEMPTY^nameISNOTEMPTY^nameNOT LIKEts_'); 
    table.query();
    while (table.next()) {
        tableName = table.getValue('name');
        check = new GlideRecord(tableName);
        if (check.get(sysid)) {
            url += tableName + '.do?sys_id=' + sysid;
            if (html) {
                var htmlUrl = '<a href="' + url + '">' + url + '</a>';
                return url;
            } 
            else {
                return url;
            } 
        }
    }
} 

Let's walk through what this code does, and then I'll show you how to use it.

First, you can see that the function (findAnywhere) takes two arguments: sysid, and html. On the first line under the function, we check if the input variable html is set to a valid boolean value. If it isn't, we default it to false. This way, if the user enters anything other than true (including nothing at all) as their second argument, we default the value to 'false'.

Next, we initialize a couple of variables for later use, and create a GlideRecord called 'table' on the sys_db_object table. This table is "the tables table". It's essentially a registry of all the other tables in the system, and some basic information about them. Later, we'll iterate over this list of every table and check each one for the sys_id we're looking for.

But before we can check each table, we want to narrow the search a little bit, to save us time, performance, and false positives. To do this, we use table.addEncodedQuery(). This allows us to combine several queries into one string:

table.addEncodedQuery('sys_update_nameISNOTEMPTY^nameISNOTEMPTY^nameNOT LIKEts_'); 

This "encoded query" verifies that the name and update name fields are not empty, and then checks that the name doesn't begin with or contain ts_. This is because tables beginning with "ts_" are text search tables, and may result in false positives.

After building our filter and querying, we want to iterate over each entry in the table. For that, we use a while loop:

while (table.next()) { }

so for each table in our list of tables, we're going to create another GlideRecord, and check if we can ".get()" the sys_id we're searching for in that table:

tableName = table.getValue('name');
check = new GlideRecord(tableName);
if (check.get(sysid)) { }

In the if block (if we've found the sys_id we're looking for in this table), we generate the URL to the record so that we can return it (either on its' own, or inside of an <a href="//"></a> HTML tag:

url += tableName + '.do?sys_id=' + sysid;

Now, if we were to put this into a script include, we could call it like so:

gs.print(findAnywhere('9ac3fd684fe1020066168ab18110c793', false)); //the second arg is optional
//output will be a URL to the record

If you wanted, you could work this functionality into an application module that would execute the search, return the URL, and redirect the browser to it! 


For those of you who don't want to risk (or, let's face it, bother) doing this yourselves, you can import my script into your instance by following these instructions:
 

  1. Click here to download my update set as an XML file. 
  2. To load into your instance, go to System Update Sets -> Retrieved Update Sets, and then click the Import Update Set from XML UI action. 
  3. Choose the XML you downloaded from the link above, then click Upload
  4. Finally, click on the "findAnywhere" update set in your list, and follow the instructions here, to preview and commit it.