How to investigate where the table References used Before Deleting a Custom Table in ServiceNow
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
2 hours ago
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
54m ago
there is no direct OOTB way for this
things to check and find
-> dictionary references (reference field, glidelist field, document id field)
-> business rules, client scripts, UI actions, reports, ACLs, script includes, UI policies
-> workflow run script, flow trigger etc
-> script actions, email notifications, email script, scheduled job
I got this code from AI tool and used incident table for example, you can try to use that script and enhance
// Set this to your custom table name
var TABLE_NAME = 'incident';
var LIKE = '%' + TABLE_NAME + '%';
function log(msg) {
gs.info(msg);
}
// 1) Dictionary: fields referencing or extending the table
log('=== Dictionary references to table or its fields ===');
var dict = new GlideRecord('sys_dictionary');
dict.addEncodedQuery('name=' + TABLE_NAME + '^ORreference=' + TABLE_NAME + '^ORinternal_typeLIKE' + TABLE_NAME);
dict.query();
while (dict.next()) {
log(dict.getValue('sys_id') + ' | ' + dict.getValue('name') + '.' + dict.getValue('element') + ' | type=' + dict.getValue('internal_type') + ' | ref=' + dict.getValue('reference'));
}
// 2) Business rules, client scripts, UI policies, etc. containing the table name
var configTables = [
'sys_script', // Business Rules
'sys_script_client', // Client Scripts
'sys_ui_policy', // UI Policies
'sys_script_include', // Script Includes
'sysauto_script', // Scheduled Scripts
'wf_workflow', // Legacy Workflows
'sys_flow_context', // Flow Designer (runtime refs)
'sys_hub_flow', // Flow definitions
'sys_report', // Reports
'sys_security_acl', // ACLs
'sys_ui_action', // UI Actions
'sys_ui_page', // UI Pages / Jelly
'sys_web_service', // Scripted Web Services
'sys_ws_operation', // SOAP ops
'sys_rest_message' // Outbound REST messages
];
function queryTableForString(table, fieldList) {
var gr = new GlideRecord(table);
var qc = gr.addQuery('sys_id', '!=', ''); // placeholder
qc.addOrCondition('name', 'CONTAINS', TABLE_NAME);
var fields = fieldList || ['script', 'condition', 'filter', 'operation', 'description', 'definition', 'template', 'url', 'rest_endpoint'];
for (var i = 0; i < fields.length; i++) {
qc.addOrCondition(fields[i], 'CONTAINS', TABLE_NAME);
}
gr.query();
while (gr.next()) {
log('[' + table + '] ' + gr.getDisplayValue() + ' (' + gr.getValue('sys_id') + ')');
}
}
log('=== Scripted/config references containing table name ===');
for (var i = 0; i < configTables.length; i++) {
queryTableForString(configTables[i]);
}
💡 If my response helped, please mark it as correct ✅ and close the thread 🔒— this helps future readers find the solution faster! 🙏
Ankur
✨ Certified Technical Architect || ✨ 9x ServiceNow MVP || ✨ ServiceNow Community Leader
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
40m ago
Hi @KrushnakumaT ,
There are no OOTB script present for this.
I've created a comprehensive Fix Script that checks all possible references to a custom table.
#Note: Please test and review the script before using it.
/*
* INSTRUCTIONS:
* 1. Replace 'u_your_custom_table' with your actual table name
* 2. Run the script
* 3. Review the output for any references
* 4. Only delete the table if no critical references are found
*/
(function checkTableReferences() {
// ===== CONFIGURATION =====
var tableName = 'u_your_custom_table'; // CHANGE THIS to your table name
// ===== INITIALIZATION =====
var results = {
tableName: tableName,
totalReferences: 0,
references: {}
};
gs.print('\n========================================');
gs.print('TABLE REFERENCE CHECKER');
gs.print('Checking references for: ' + tableName);
gs.print('========================================\n');
// ===== 1. CHECK DICTIONARY ENTRIES (Fields referencing this table) =====
gs.print('1. Checking Dictionary Entries (Reference Fields)...');
var dictGr = new GlideRecord('sys_dictionary');
dictGr.addQuery('reference', tableName);
dictGr.query();
var dictResults = [];
while (dictGr.next()) {
dictResults.push({
table: dictGr.name.toString(),
field: dictGr.element.toString(),
label: dictGr.column_label.toString(),
sys_id: dictGr.sys_id.toString()
});
}
if (dictResults.length > 0) {
results.references.dictionaryEntries = dictResults;
results.totalReferences += dictResults.length;
gs.print(' FOUND ' + dictResults.length + ' reference field(s):');
for (var i = 0; i < dictResults.length; i++) {
gs.print(' - ' + dictResults[i].table + '.' + dictResults[i].field + ' (' + dictResults[i].label + ')');
}
} else {
gs.print(' No reference fields found.');
}
// ===== 2. CHECK BUSINESS RULES =====
gs.print('\n2. Checking Business Rules...');
var brGr = new GlideRecord('sys_script');
brGr.addQuery('collection', tableName)
.addOrCondition('script', 'CONTAINS', tableName);
brGr.query();
var brResults = [];
while (brGr.next()) {
brResults.push({
name: brGr.name.toString(),
table: brGr.collection.toString(),
when: brGr.when.toString(),
active: brGr.active.toString(),
sys_id: brGr.sys_id.toString()
});
}
if (brResults.length > 0) {
results.references.businessRules = brResults;
results.totalReferences += brResults.length;
gs.print(' FOUND ' + brResults.length + ' business rule(s):');
for (var j = 0; j < brResults.length; j++) {
gs.print(' - ' + brResults[j].name + ' (Table: ' + brResults[j].table + ')');
}
} else {
gs.print(' No business rules found.');
}
// ===== 3. CHECK CLIENT SCRIPTS =====
gs.print('\n3. Checking Client Scripts...');
var csGr = new GlideRecord('sys_script_client');
csGr.addQuery('table', tableName)
.addOrCondition('script', 'CONTAINS', tableName);
csGr.query();
var csResults = [];
while (csGr.next()) {
csResults.push({
name: csGr.name.toString(),
table: csGr.table.toString(),
type: csGr.type.toString(),
active: csGr.active.toString(),
sys_id: csGr.sys_id.toString()
});
}
if (csResults.length > 0) {
results.references.clientScripts = csResults;
results.totalReferences += csResults.length;
gs.print(' FOUND ' + csResults.length + ' client script(s):');
for (var k = 0; k < csResults.length; k++) {
gs.print(' - ' + csResults[k].name + ' (' + csResults[k].type + ')');
}
} else {
gs.print(' No client scripts found.');
}
// ===== 4. CHECK UI POLICIES =====
gs.print('\n4. Checking UI Policies...');
var uiPolicyGr = new GlideRecord('sys_ui_policy');
uiPolicyGr.addQuery('table', tableName);
uiPolicyGr.query();
var uiPolicyResults = [];
while (uiPolicyGr.next()) {
uiPolicyResults.push({
short_description: uiPolicyGr.short_description.toString(),
table: uiPolicyGr.table.toString(),
active: uiPolicyGr.active.toString(),
sys_id: uiPolicyGr.sys_id.toString()
});
}
if (uiPolicyResults.length > 0) {
results.references.uiPolicies = uiPolicyResults;
results.totalReferences += uiPolicyResults.length;
gs.print(' FOUND ' + uiPolicyResults.length + ' UI policy(ies):');
for (var l = 0; l < uiPolicyResults.length; l++) {
gs.print(' - ' + uiPolicyResults[l].short_description);
}
} else {
gs.print(' No UI policies found.');
}
// ===== 5. CHECK UI ACTIONS =====
gs.print('\n5. Checking UI Actions...');
var uiActionGr = new GlideRecord('sys_ui_action');
uiActionGr.addQuery('table', tableName)
.addOrCondition('script', 'CONTAINS', tableName);
uiActionGr.query();
var uiActionResults = [];
while (uiActionGr.next()) {
uiActionResults.push({
name: uiActionGr.name.toString(),
table: uiActionGr.table.toString(),
action_name: uiActionGr.action_name.toString(),
active: uiActionGr.active.toString(),
sys_id: uiActionGr.sys_id.toString()
});
}
if (uiActionResults.length > 0) {
results.references.uiActions = uiActionResults;
results.totalReferences += uiActionResults.length;
gs.print(' FOUND ' + uiActionResults.length + ' UI action(s):');
for (var m = 0; m < uiActionResults.length; m++) {
gs.print(' - ' + uiActionResults[m].name);
}
} else {
gs.print(' No UI actions found.');
}
// ===== 6. CHECK ACL RULES =====
gs.print('\n6. Checking ACL Rules...');
var aclGr = new GlideRecord('sys_security_acl');
aclGr.addQuery('name', 'CONTAINS', tableName);
aclGr.query();
var aclResults = [];
while (aclGr.next()) {
aclResults.push({
name: aclGr.name.toString(),
operation: aclGr.operation.toString(),
active: aclGr.active.toString(),
sys_id: aclGr.sys_id.toString()
});
}
if (aclResults.length > 0) {
results.references.aclRules = aclResults;
results.totalReferences += aclResults.length;
gs.print(' FOUND ' + aclResults.length + ' ACL rule(s):');
for (var n = 0; n < aclResults.length; n++) {
gs.print(' - ' + aclResults[n].name + ' (' + aclResults[n].operation + ')');
}
} else {
gs.print(' No ACL rules found.');
}
// ===== 7. CHECK WORKFLOWS =====
gs.print('\n7. Checking Workflows...');
var wfGr = new GlideRecord('wf_workflow');
wfGr.addQuery('table', tableName);
wfGr.query();
var wfResults = [];
while (wfGr.next()) {
wfResults.push({
name: wfGr.name.toString(),
table: wfGr.table.toString(),
active: wfGr.active.toString(),
sys_id: wfGr.sys_id.toString()
});
}
if (wfResults.length > 0) {
results.references.workflows = wfResults;
results.totalReferences += wfResults.length;
gs.print(' FOUND ' + wfResults.length + ' workflow(s):');
for (var o = 0; o < wfResults.length; o++) {
gs.print(' - ' + wfResults[o].name);
}
} else {
gs.print(' No workflows found.');
}
// ===== 8. CHECK SCRIPT INCLUDES =====
gs.print('\n8. Checking Script Includes...');
var siGr = new GlideRecord('sys_script_include');
siGr.addQuery('script', 'CONTAINS', tableName);
siGr.query();
var siResults = [];
while (siGr.next()) {
siResults.push({
name: siGr.name.toString(),
api_name: siGr.api_name.toString(),
active: siGr.active.toString(),
sys_id: siGr.sys_id.toString()
});
}
if (siResults.length > 0) {
results.references.scriptIncludes = siResults;
results.totalReferences += siResults.length;
gs.print(' FOUND ' + siResults.length + ' script include(s):');
for (var p = 0; p < siResults.length; p++) {
gs.print(' - ' + siResults[p].name);
}
} else {
gs.print(' No script includes found.');
}
// ===== 9. CHECK SCHEDULED JOBS =====
gs.print('\n9. Checking Scheduled Jobs...');
var schedGr = new GlideRecord('sysauto_script');
schedGr.addQuery('script', 'CONTAINS', tableName);
schedGr.query();
var schedResults = [];
while (schedGr.next()) {
schedResults.push({
name: schedGr.name.toString(),
active: schedGr.active.toString(),
sys_id: schedGr.sys_id.toString()
});
}
if (schedResults.length > 0) {
results.references.scheduledJobs = schedResults;
results.totalReferences += schedResults.length;
gs.print(' FOUND ' + schedResults.length + ' scheduled job(s):');
for (var q = 0; q < schedResults.length; q++) {
gs.print(' - ' + schedResults[q].name);
}
} else {
gs.print(' No scheduled jobs found.');
}
// ===== 10. CHECK REPORTS =====
gs.print('\n10. Checking Reports...');
var reportGr = new GlideRecord('sys_report');
reportGr.addQuery('table', tableName);
reportGr.query();
var reportResults = [];
while (reportGr.next()) {
reportResults.push({
title: reportGr.title.toString(),
table: reportGr.table.toString(),
sys_id: reportGr.sys_id.toString()
});
}
if (reportResults.length > 0) {
results.references.reports = reportResults;
results.totalReferences += reportResults.length;
gs.print(' FOUND ' + reportResults.length + ' report(s):');
for (var r = 0; r < reportResults.length; r++) {
gs.print(' - ' + reportResults[r].title);
}
} else {
gs.print(' No reports found.');
}
// ===== 11. CHECK RECORD COUNT =====
gs.print('\n11. Checking Record Count...');
var recordGr = new GlideRecord(tableName);
if (recordGr.isValid()) {
recordGr.query();
var recordCount = recordGr.getRowCount();
results.recordCount = recordCount;
gs.print(' Table contains ' + recordCount + ' record(s).');
} else {
gs.print(' ERROR: Table "' + tableName + '" does not exist or is invalid.');
results.error = 'Table does not exist or is invalid';
}
// ===== FINAL SUMMARY =====
gs.print('\n========================================');
gs.print('SUMMARY');
gs.print('========================================');
gs.print('Table: ' + tableName);
gs.print('Total References Found: ' + results.totalReferences);
gs.print('Record Count: ' + (results.recordCount || 'N/A'));
if (results.totalReferences === 0 && (!results.recordCount || results.recordCount === 0)) {
gs.print('\n✓ SAFE TO DELETE: No references or records found.');
} else if (results.totalReferences === 0 && results.recordCount > 0) {
gs.print('\n⚠ WARNING: No references found, but table contains ' + results.recordCount + ' record(s).');
gs.print(' Consider backing up data before deletion.');
} else {
gs.print('\n✗ NOT SAFE TO DELETE: References found in the system.');
gs.print(' Review and remove dependencies before deleting the table.');
}
gs.print('========================================\n');
// Return results object for programmatic access if needed
return results;
})();
This Script Checks the below:
- Dictionary Entries
- Business Rules
- Client Scripts
- UI Policies
- UI Actions
- ACL Rules
- Workflows
- Script Includes
- Scheduled Jobs
- Reports
- Record Count
Output Interpretation:
- SAFE TO DELETE: No references or records found
- WARNING: No references but contains data (backup recommended)
- NOT SAFE: References found - must be removed first
Best Practices:
- Run this in a sub-production environment first
- Document all found references
- Create a backup of the table data before deletion
If this answer helped you, please mark it as the accepted answer ✅ and mark it as helpful 👍.
