DatabaseView
Creates a Database View (sys_db_view) — a read-only virtual table that joins two
or more real tables into a single reportable pseudo-table. A view stores no data
of its own; it is a live join definition consumed by reporting, lists, and other
queries.
Signature
DatabaseView(config)
Usage
In a customer scope (x_*), name must include the scope prefix; it must be
unique across all database views. Child table and field entries require
explicit $ids because the same table or field can appear more than once in a
single view.
import { DatabaseView } from '@servicenow/sdk/core'
DatabaseView({
name: 'x_snc_incident_with_caller',
label: 'Incidents With Caller',
tables: [
{
$id: Now.ID['incident-table'],
table: 'incident',
variablePrefix: 'inc',
fields: [
{ $id: Now.ID['incident-number'], field: 'number' },
{ $id: Now.ID['incident-short-description'], field: 'short_description' },
{ $id: Now.ID['incident-caller-id'], field: 'caller_id' },
],
},
{
$id: Now.ID['caller-table'],
table: 'sys_user',
variablePrefix: 'usr',
whereClause: 'inc_caller_id=usr_sys_id',
fields: [
{ $id: Now.ID['caller-sys-id'], field: 'sys_id' },
{ $id: Now.ID['caller-name'], field: 'name' },
{ $id: Now.ID['caller-email'], field: 'email' },
],
},
],
})
Parameters
config
DatabaseViewConfig
The Database View configuration object.
Properties:
-
name (required):
stringName of the database view. This is the record's identity key: the platform enforces uniqueness of the normalized name across all database views, soDatabaseViewintentionally omits a top-level$id. The platform silently normalizes this value (lowercase, non-alphanumeric characters replaced with_) before storing it, and the Fluent build coalesces onnameacross rebuilds — supply an already-normalized name to avoid a duplicate view being created on the next build.In a customer scope (any scope starting with x_), name must also start with the scope prefix. In the global scope,
namemust start with the customu_prefix. -
label (optional, default:
''):stringDisplay label shown in admin views. -
plural (optional, default:
''):stringPlural display label. -
description (optional, default:
''):stringFree-text description of the view's purpose. -
tables (required):
DatabaseViewTable[]The tables joined into this view, in join order. May be empty — ServiceNow allows database views with no joined tables.DatabaseViewTableproperties:-
$id (required):
Now.ID['...']- Explicit ID for the joined-table entry. Required because no natural coalesce key exists. -
table (required):
TableNameThe table to join into the view. In a scoped app, prefer a table in the same scope, or a scoped table that extends an out-of-box table, when targeting platform data. -
variablePrefix (required):
stringDisambiguates this table's fields insidewhereClause(e.g.usrforsys_user). The platform rejects prefixes containing an underscore or exceeding 30 characters. Must be unique across every table in the same view — a collision produces a broken or ambiguous join and is not caught by the platform itself. -
leftJoin (optional, default:
false):booleanfalseproduces an INNER JOIN — only rows with matches in every joined table appear.trueproduces a LEFT OUTER JOIN — all rows from prior tables appear, with empty values for unmatched columns from this table. -
order (optional, default:
100):numberJoin order relative to other tables in this view. Affects query performance on large tables — put the most selective/smallest table first. -
whereClause (optional, default:
''):stringA raw join/filter predicate usingvariablePrefix-qualified field names, e.g.usr_sys_id=role_user. This is not an encoded query string. -
active (optional, default:
true):booleanWhether this joined table is active. -
fields (optional, default:
[]):Array<DatabaseViewField>Columns fromtableto expose in the view. Each entry is an object with a required$idand afieldname. The$idis the unique identifier for thesys_db_view_table_fieldrecord, matching the platform'ssys_id. Provide a unique$idfor every field; use distinct$ids when the same field must appear more than once under the same view table. Many real views join a table purely for filtering (viawhereClause) without exposing any of its columns — omit or leave empty in that case.
-
-
protectionPolicy (optional):
'read' | 'protected'Controls edit access for other developers after the application is installed.'read': Others can view this record's configuration but cannot change it.'protected': Others cannot change this record.- Omit to allow other developers to customize this record.
Identity Model
DatabaseView does not expose a top-level $id. The platform enforces that the
normalized name is unique across all sys_db_view records, so name is the stable identifier and the
Fluent build coalesces on it across rebuilds.
Child records — DatabaseViewTable and DatabaseViewField — still require
$id because the same table can be joined multiple times in the same view
under different variablePrefix values, which makes (view, table) an
unreliable coalesce key.
DatabaseViewField
Field entry in fields.
-
$id (required):
Now.ID['...']- Explicit ID for the table field. -
field (required):
string- Column name from the joinedtableto expose in the view. IDE autocomplete is available for fields of known tables.
Validation Rules
-
Name normalization:
namemust already be normalized (lowercase, non-alphanumeric characters replaced with_) — the plugin emits a build error if it isn't, since a mismatch would cause the next build to create a duplicate view instead of updating this one. -
Scope prefix: in a customer scope (any scope starting with
x_),namemust start with${scope}_— a build error if missing. In the global scope,namemust start with the customu_prefix instead — also a build error if missing. -
Variable prefix format:
variablePrefixmust not contain an underscore and must be 30 characters or fewer. -
Unique variable prefix per view: two
tables[]entries in the same view must not share the samevariablePrefix— this produces an ambiguous join and is rejected with a build error.
Examples
Basic database view
The simplest valid view — a single joined table with no field selection. The
name must include the scope prefix and be unique; the joined table needs a
unique $id.
import { DatabaseView } from '@servicenow/sdk/core'
export const example = DatabaseView({
name: 'x_snc_database_view_basic',
tables: [{
$id: Now.ID['database-view-basic-table'],
table: 'incident',
variablePrefix: 'inc',
}],
})
Database view with field selection
Selects specific columns from the joined table to expose in the view. Each
joined table and each field within a table needs a unique $id.
import { DatabaseView } from '@servicenow/sdk/core'
export const example = DatabaseView({
name: 'x_snc_database_view_with_fields',
label: 'Incidents With Selected Fields',
tables: [
{
$id: Now.ID['database-view-with-fields-table'],
table: 'incident',
variablePrefix: 'inc',
fields: [
{ $id: Now.ID['with-fields-number'], field: 'number' },
{ $id: Now.ID['with-fields-short-description'], field: 'short_description' },
{ $id: Now.ID['with-fields-priority'], field: 'priority' },
],
},
],
})
Database view with a left join
Joins a second table with leftJoin so rows with no match still appear.
import { DatabaseView } from '@servicenow/sdk/core'
export const example = DatabaseView({
name: 'x_snc_database_view_left_join',
description: 'Incidents joined to assignment group, including incidents with no group',
tables: [
{ $id: Now.ID['database-view-left-join-incident-table'], table: 'incident', variablePrefix: 'inc', order: 100 },
{
$id: Now.ID['database-view-left-join-group-table'],
table: 'sys_user_group',
variablePrefix: 'grp',
order: 200,
leftJoin: true,
whereClause: 'inc_assignment_group=grp_sys_id',
fields: [
{ $id: Now.ID['left-join-group-sys-id'], field: 'sys_id' },
{ $id: Now.ID['left-join-group-name'], field: 'name' }
],
},
],
})
Advanced database view
Combines multiple joined tables, field selection, a left join, and a custom filter clause.
import { DatabaseView } from '@servicenow/sdk/core'
export const example = DatabaseView({
name: 'x_snc_database_view_advanced',
label: 'Incidents With Caller And Group',
plural: 'Incidents With Caller And Group',
description: 'Joins incidents to caller and assignment group for reporting',
tables: [
{
$id: Now.ID['database-view-advanced-incident-table'],
table: 'incident',
variablePrefix: 'inc',
order: 100,
fields: [
{ $id: Now.ID['advanced-incident-number'], field: 'number' },
{ $id: Now.ID['advanced-incident-short-description'], field: 'short_description' },
{ $id: Now.ID['advanced-incident-caller-id'], field: 'caller_id' },
{ $id: Now.ID['advanced-incident-assignment-group'], field: 'assignment_group' },
],
},
{
$id: Now.ID['database-view-advanced-caller-table'],
table: 'sys_user',
variablePrefix: 'usr',
order: 200,
whereClause: 'inc_caller_id=usr_sys_id',
fields: [
{ $id: Now.ID['advanced-caller-sys-id'], field: 'sys_id' },
{ $id: Now.ID['advanced-caller-name'], field: 'name' },
{ $id: Now.ID['advanced-caller-email'], field: 'email' },
],
},
{
$id: Now.ID['database-view-advanced-group-table'],
table: 'sys_user_group',
variablePrefix: 'grp',
order: 300,
leftJoin: true,
whereClause: 'inc_assignment_group=grp_sys_id',
fields: [
{ $id: Now.ID['advanced-group-sys-id'], field: 'sys_id' },
{ $id: Now.ID['advanced-group-name'], field: 'name' },
],
},
],
})