Core Concepts
What are the different tables in ServiceNow, and what does 'table extends table' mean?
The question
The Intent Behind This Question
Table inheritance is one of ServiceNow's most important concepts. It affects how data is stored, how scripts execute, and how security is applied. Interviewers ask this to check if you understand why a Business Rule on 'task' fires on incidents too.
Tables in ServiceNow
Every piece of data in ServiceNow lives in a table. Tables are like database tables — they have columns (fields) and rows (records). But ServiceNow tables support inheritance, which means one table can extend another and inherit all its fields.
The Task Table Hierarchy
// task (base table) // ├── Fields: number, state, priority, assigned_to, short_description // │ // ├── incident (extends task) // │ └── Adds: category, subcategory, caller_id, resolve_time // │ // ├── change_request (extends task) // │ └── Adds: risk, type, planned_start_date, cab_required // │ // ├── problem (extends task) // │ └── Adds: known_error, root_cause, workaround // │ // ├── sc_task (extends task) // │ └── Adds: request_item, catalog fields // │ // └── sc_req_item (extends task) // └── Adds: cat_item, stage, price // NOTE: sc_req_item extends task directly, NOT sc_task
What 'Extends' Means in Practice
- Field inheritance: The
incidenttable has all fields fromtask(number, state, priority...) PLUS its own fields (category, caller_id). You don't need to recreate common fields. - Script inheritance: A Business Rule on the
tasktable fires for ALL child tables — incidents, changes, problems, etc. This is powerful but dangerous if unintended. - ACL inheritance: A security rule on
taskapplies to all extending tables unless overridden at the child level. - Physical storage: ServiceNow uses single-table inheritance — child records are physically stored in the parent table's database. A
sys_class_namefield acts as a discriminator to identify the record type.
// Important: Querying 'task' returns EVERYTHING
var gr = new GlideRecord('task');
gr.addQuery('assigned_to', userId);
gr.query();
// Returns incidents + changes + problems + catalog tasks + ...
// Could be hundreds of thousands of records!
// If you only want incidents, query the child table:
var gr = new GlideRecord('incident');
gr.addQuery('assigned_to', userId);
gr.query();
// Returns only incidentsOther Important Tables (Non-Task)
sys_user— User recordssys_user_group— Group recordscmdb_ci— Configuration Items (extends to cmdb_ci_server, cmdb_ci_database, etc.)kb_knowledge— Knowledge articlessys_choice— Dropdown/choice list values
💡 Interview Tip
Always check if the table you're working with extends another table before writing a Business Rule. The classic mistake: writing a BR on 'task' thinking it only affects your custom task type, then discovering it fires on every incident, change, and problem in the system.