data-policies

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Data Policies & Dictionary for ServiceNow

ServiceNow 数据策略与字典

Data Policies enforce data integrity rules. Dictionary controls schema and field behavior.
数据策略用于强制执行数据完整性规则,字典用于控制表结构与字段行为。

Architecture

架构

Dictionary (sys_dictionary)
    ├── Field Definition
    │   ├── Type, Length, Default
    │   └── Dependent Field
    └── Dictionary Overrides (sys_dictionary_override)

Data Policy (sys_data_policy2)
    └── Data Policy Rules (sys_data_policy_rule)
        └── Condition-based field behaviors
Dictionary (sys_dictionary)
    ├── Field Definition
    │   ├── Type, Length, Default
    │   └── Dependent Field
    └── Dictionary Overrides (sys_dictionary_override)

Data Policy (sys_data_policy2)
    └── Data Policy Rules (sys_data_policy_rule)
        └── Condition-based field behaviors

Key Tables

核心表

TablePurpose
sys_dictionary
Field definitions
sys_dictionary_override
Scoped overrides
sys_data_policy2
Data policies
sys_data_policy_rule
Policy rules
sys_db_object
Table definitions
表名用途
sys_dictionary
字段定义
sys_dictionary_override
作用域覆盖配置
sys_data_policy2
数据策略
sys_data_policy_rule
策略规则
sys_db_object
表定义

Dictionary Management (ES5)

字典管理(仅支持ES5)

Create Table

创建表

javascript
// Create custom table (ES5 ONLY!)
var table = new GlideRecord('sys_db_object');
table.initialize();

table.setValue('name', 'u_custom_table');
table.setValue('label', 'Custom Table');
table.setValue('super_class', 'task');  // Extends task
table.setValue('is_extendable', true);
table.setValue('create_access_controls', true);
table.setValue('live_feed_enabled', false);

table.insert();
javascript
// Create custom table (ES5 ONLY!)
var table = new GlideRecord('sys_db_object');
table.initialize();

table.setValue('name', 'u_custom_table');
table.setValue('label', 'Custom Table');
table.setValue('super_class', 'task');  // Extends task
table.setValue('is_extendable', true);
table.setValue('create_access_controls', true);
table.setValue('live_feed_enabled', false);

table.insert();

Create Field

创建字段

javascript
// Create field on table (ES5 ONLY!)
var field = new GlideRecord('sys_dictionary');
field.initialize();

// Table and element
field.setValue('name', 'u_custom_table');
field.setValue('element', 'u_customer_name');

// Field properties
field.setValue('column_label', 'Customer Name');
field.setValue('internal_type', 'string');
field.setValue('max_length', 100);
field.setValue('mandatory', false);
field.setValue('read_only', false);
field.setValue('display', false);
field.setValue('active', true);

// Default value
field.setValue('default_value', '');

// Reference field specific
// field.setValue('reference', 'customer_account');
// field.setValue('reference_qual', 'active=true');

field.insert();
javascript
// Create field on table (ES5 ONLY!)
var field = new GlideRecord('sys_dictionary');
field.initialize();

// Table and element
field.setValue('name', 'u_custom_table');
field.setValue('element', 'u_customer_name');

// Field properties
field.setValue('column_label', 'Customer Name');
field.setValue('internal_type', 'string');
field.setValue('max_length', 100);
field.setValue('mandatory', false);
field.setValue('read_only', false);
field.setValue('display', false);
field.setValue('active', true);

// Default value
field.setValue('default_value', '');

// Reference field specific
// field.setValue('reference', 'customer_account');
// field.setValue('reference_qual', 'active=true');

field.insert();

Field Types

字段类型

javascript
// Common field types
var FIELD_TYPES = {
    STRING: 'string',
    INTEGER: 'integer',
    DECIMAL: 'decimal',
    BOOLEAN: 'boolean',
    GLIDE_DATE: 'glide_date',
    GLIDE_DATE_TIME: 'glide_date_time',
    REFERENCE: 'reference',
    CHOICE: 'choice',
    JOURNAL: 'journal',
    JOURNAL_INPUT: 'journal_input',
    HTML: 'html',
    URL: 'url',
    EMAIL: 'email',
    SCRIPT: 'script',
    CONDITIONS: 'conditions'
};

// Create different field types (ES5 ONLY!)
function createField(tableName, fieldDef) {
    var field = new GlideRecord('sys_dictionary');
    field.initialize();
    field.setValue('name', tableName);
    field.setValue('element', fieldDef.name);
    field.setValue('column_label', fieldDef.label);
    field.setValue('internal_type', fieldDef.type);

    if (fieldDef.maxLength) {
        field.setValue('max_length', fieldDef.maxLength);
    }

    if (fieldDef.reference) {
        field.setValue('reference', fieldDef.reference);
    }

    if (fieldDef.choices) {
        field.setValue('choice', 1);  // Has choices
    }

    return field.insert();
}
javascript
// Common field types
var FIELD_TYPES = {
    STRING: 'string',
    INTEGER: 'integer',
    DECIMAL: 'decimal',
    BOOLEAN: 'boolean',
    GLIDE_DATE: 'glide_date',
    GLIDE_DATE_TIME: 'glide_date_time',
    REFERENCE: 'reference',
    CHOICE: 'choice',
    JOURNAL: 'journal',
    JOURNAL_INPUT: 'journal_input',
    HTML: 'html',
    URL: 'url',
    EMAIL: 'email',
    SCRIPT: 'script',
    CONDITIONS: 'conditions'
};

// Create different field types (ES5 ONLY!)
function createField(tableName, fieldDef) {
    var field = new GlideRecord('sys_dictionary');
    field.initialize();
    field.setValue('name', tableName);
    field.setValue('element', fieldDef.name);
    field.setValue('column_label', fieldDef.label);
    field.setValue('internal_type', fieldDef.type);

    if (fieldDef.maxLength) {
        field.setValue('max_length', fieldDef.maxLength);
    }

    if (fieldDef.reference) {
        field.setValue('reference', fieldDef.reference);
    }

    if (fieldDef.choices) {
        field.setValue('choice', 1);  // Has choices
    }

    return field.insert();
}

Create Choices

创建选项列表

javascript
// Create choice list values (ES5 ONLY!)
function createChoices(tableName, fieldName, choices) {
    for (var i = 0; i < choices.length; i++) {
        var choice = new GlideRecord('sys_choice');
        choice.initialize();
        choice.setValue('name', tableName);
        choice.setValue('element', fieldName);
        choice.setValue('value', choices[i].value);
        choice.setValue('label', choices[i].label);
        choice.setValue('sequence', (i + 1) * 10);
        choice.setValue('inactive', false);
        choice.insert();
    }
}

// Usage
createChoices('incident', 'u_custom_status', [
    { value: 'pending', label: 'Pending Review' },
    { value: 'approved', label: 'Approved' },
    { value: 'rejected', label: 'Rejected' }
]);
javascript
// Create choice list values (ES5 ONLY!)
function createChoices(tableName, fieldName, choices) {
    for (var i = 0; i < choices.length; i++) {
        var choice = new GlideRecord('sys_choice');
        choice.initialize();
        choice.setValue('name', tableName);
        choice.setValue('element', fieldName);
        choice.setValue('value', choices[i].value);
        choice.setValue('label', choices[i].label);
        choice.setValue('sequence', (i + 1) * 10);
        choice.setValue('inactive', false);
        choice.insert();
    }
}

// Usage
createChoices('incident', 'u_custom_status', [
    { value: 'pending', label: 'Pending Review' },
    { value: 'approved', label: 'Approved' },
    { value: 'rejected', label: 'Rejected' }
]);

Dictionary Overrides (ES5)

字典覆盖配置(仅支持ES5)

Create Override

创建覆盖规则

javascript
// Create dictionary override for scoped app (ES5 ONLY!)
var override = new GlideRecord('sys_dictionary_override');
override.initialize();

// Reference the base field
override.setValue('base_table', 'task');
override.setValue('base_element', 'short_description');

// Target table
override.setValue('name', 'u_custom_table');

// Override properties
override.setValue('column_label', 'Request Summary');
override.setValue('mandatory', true);
override.setValue('read_only', false);
override.setValue('max_length', 200);

// Default value override
override.setValue('default_value', '');

override.insert();
javascript
// Create dictionary override for scoped app (ES5 ONLY!)
var override = new GlideRecord('sys_dictionary_override');
override.initialize();

// Reference the base field
override.setValue('base_table', 'task');
override.setValue('base_element', 'short_description');

// Target table
override.setValue('name', 'u_custom_table');

// Override properties
override.setValue('column_label', 'Request Summary');
override.setValue('mandatory', true);
override.setValue('read_only', false);
override.setValue('max_length', 200);

// Default value override
override.setValue('default_value', '');

override.insert();

Data Policies (ES5)

数据策略(仅支持ES5)

Create Data Policy

创建数据策略

javascript
// Create data policy (ES5 ONLY!)
var policy = new GlideRecord('sys_data_policy2');
policy.initialize();

policy.setValue('model_table', 'incident');
policy.setValue('short_description', 'Resolution Fields Required on Resolve');
policy.setValue('active', true);

// Conditions - when policy applies
policy.setValue('conditions', 'state=6');  // Resolved state

// Apply to forms
policy.setValue('apply_to_client', true);
policy.setValue('apply_to_import_sets', true);
policy.setValue('apply_to_soap', true);

// Reverse
policy.setValue('reverse_if_false', true);

var policySysId = policy.insert();

// Add policy rules
addDataPolicyRule(policySysId, 'resolution_code', true, false, false);
addDataPolicyRule(policySysId, 'close_notes', true, false, false);
javascript
// Create data policy (ES5 ONLY!)
var policy = new GlideRecord('sys_data_policy2');
policy.initialize();

policy.setValue('model_table', 'incident');
policy.setValue('short_description', 'Resolution Fields Required on Resolve');
policy.setValue('active', true);

// Conditions - when policy applies
policy.setValue('conditions', 'state=6');  // Resolved state

// Apply to forms
policy.setValue('apply_to_client', true);
policy.setValue('apply_to_import_sets', true);
policy.setValue('apply_to_soap', true);

// Reverse
policy.setValue('reverse_if_false', true);

var policySysId = policy.insert();

// Add policy rules
addDataPolicyRule(policySysId, 'resolution_code', true, false, false);
addDataPolicyRule(policySysId, 'close_notes', true, false, false);

Add Policy Rules

添加策略规则

javascript
// Add data policy rule (ES5 ONLY!)
function addDataPolicyRule(policySysId, fieldName, mandatory, readOnly, hidden) {
    var rule = new GlideRecord('sys_data_policy_rule');
    rule.initialize();
    rule.setValue('sys_data_policy', policySysId);
    rule.setValue('field', fieldName);
    rule.setValue('mandatory', mandatory);
    rule.setValue('read_only', readOnly);
    rule.setValue('visible', !hidden);
    return rule.insert();
}
javascript
// Add data policy rule (ES5 ONLY!)
function addDataPolicyRule(policySysId, fieldName, mandatory, readOnly, hidden) {
    var rule = new GlideRecord('sys_data_policy_rule');
    rule.initialize();
    rule.setValue('sys_data_policy', policySysId);
    rule.setValue('field', fieldName);
    rule.setValue('mandatory', mandatory);
    rule.setValue('read_only', readOnly);
    rule.setValue('visible', !hidden);
    return rule.insert();
}

Complex Data Policy

复杂数据策略

javascript
// Data policy with scripted condition (ES5 ONLY!)
var policy = new GlideRecord('sys_data_policy2');
policy.initialize();

policy.setValue('model_table', 'change_request');
policy.setValue('short_description', 'High Risk Change Requirements');
policy.setValue('active', true);

// Use scripted condition for complex logic
policy.setValue('use_as_condition', true);
policy.setValue('script',
    '(function checkCondition(current) {\n' +
    '    // High risk changes require additional fields\n' +
    '    if (current.risk == "high") {\n' +
    '        return true;\n' +
    '    }\n' +
    '    \n' +
    '    // Also apply to changes affecting critical CIs\n' +
    '    if (current.cmdb_ci) {\n' +
    '        var ci = current.cmdb_ci.getRefRecord();\n' +
    '        if (ci.business_criticality == "1 - most critical") {\n' +
    '            return true;\n' +
    '        }\n' +
    '    }\n' +
    '    \n' +
    '    return false;\n' +
    '})(current);'
);

var policySysId = policy.insert();

// Require additional documentation for high risk
addDataPolicyRule(policySysId, 'implementation_plan', true, false, false);
addDataPolicyRule(policySysId, 'backout_plan', true, false, false);
addDataPolicyRule(policySysId, 'test_plan', true, false, false);
addDataPolicyRule(policySysId, 'justification', true, false, false);
javascript
// Data policy with scripted condition (ES5 ONLY!)
var policy = new GlideRecord('sys_data_policy2');
policy.initialize();

policy.setValue('model_table', 'change_request');
policy.setValue('short_description', 'High Risk Change Requirements');
policy.setValue('active', true);

// Use scripted condition for complex logic
policy.setValue('use_as_condition', true);
policy.setValue('script',
    '(function checkCondition(current) {\n' +
    '    // High risk changes require additional fields\n' +
    '    if (current.risk == "high") {\n' +
    '        return true;\n' +
    '    }\n' +
    '    \n' +
    '    // Also apply to changes affecting critical CIs\n' +
    '    if (current.cmdb_ci) {\n' +
    '        var ci = current.cmdb_ci.getRefRecord();\n' +
    '        if (ci.business_criticality == "1 - most critical") {\n' +
    '            return true;\n' +
    '        }\n' +
    '    }\n' +
    '    \n' +
    '    return false;\n' +
    '})(current);'
);

var policySysId = policy.insert();

// Require additional documentation for high risk
addDataPolicyRule(policySysId, 'implementation_plan', true, false, false);
addDataPolicyRule(policySysId, 'backout_plan', true, false, false);
addDataPolicyRule(policySysId, 'test_plan', true, false, false);
addDataPolicyRule(policySysId, 'justification', true, false, false);

Field Validation (ES5)

字段验证(仅支持ES5)

Dictionary Attribute Validation

字典属性验证

javascript
// Add validation to dictionary field (ES5 ONLY!)
var field = new GlideRecord('sys_dictionary');
if (field.get('name', 'incident').get('element', 'u_email')) {
    // Add regex validation
    field.setValue('attributes', 'validate=email');
    field.update();
}

// Common validation attributes
var VALIDATION_ATTRIBUTES = {
    EMAIL: 'validate=email',
    PHONE: 'validate=phone_number',
    URL: 'validate=url',
    CUSTOM: 'validate=script'  // Uses script in Calculated Value
};
javascript
// Add validation to dictionary field (ES5 ONLY!)
var field = new GlideRecord('sys_dictionary');
if (field.get('name', 'incident').get('element', 'u_email')) {
    // Add regex validation
    field.setValue('attributes', 'validate=email');
    field.update();
}

// Common validation attributes
var VALIDATION_ATTRIBUTES = {
    EMAIL: 'validate=email',
    PHONE: 'validate=phone_number',
    URL: 'validate=url',
    CUSTOM: 'validate=script'  // Uses script in Calculated Value
};

Script Validation

脚本验证

javascript
// Calculated field with validation (ES5 ONLY!)
// Set in Dictionary > Calculated Value

// Check phone format
(function calculate() {
    var phone = current.getValue('u_phone');
    if (!phone) return '';

    // Format validation
    var phonePattern = /^\+?[1-9]\d{1,14}$/;
    if (!phonePattern.test(phone.replace(/[\s\-\(\)]/g, ''))) {
        gs.addErrorMessage('Invalid phone number format');
        return '';
    }

    return phone;
})();
javascript
// Calculated field with validation (ES5 ONLY!)
// Set in Dictionary > Calculated Value

// Check phone format
(function calculate() {
    var phone = current.getValue('u_phone');
    if (!phone) return '';

    // Format validation
    var phonePattern = /^\+?[1-9]\d{1,14}$/;
    if (!phonePattern.test(phone.replace(/[\s\-\(\)]/g, ''))) {
        gs.addErrorMessage('Invalid phone number format');
        return '';
    }

    return phone;
})();

Schema Queries (ES5)

结构查询(仅支持ES5)

Get Table Fields

获取表字段

javascript
// Get all fields for a table (ES5 ONLY!)
function getTableFields(tableName) {
    var fields = [];

    var dict = new GlideRecord('sys_dictionary');
    dict.addQuery('name', tableName);
    dict.addQuery('internal_type', '!=', 'collection');
    dict.addQuery('active', true);
    dict.orderBy('element');
    dict.query();

    while (dict.next()) {
        fields.push({
            name: dict.getValue('element'),
            label: dict.getValue('column_label'),
            type: dict.getValue('internal_type'),
            mandatory: dict.getValue('mandatory') === 'true',
            reference: dict.getValue('reference'),
            maxLength: dict.getValue('max_length')
        });
    }

    return fields;
}
javascript
// Get all fields for a table (ES5 ONLY!)
function getTableFields(tableName) {
    var fields = [];

    var dict = new GlideRecord('sys_dictionary');
    dict.addQuery('name', tableName);
    dict.addQuery('internal_type', '!=', 'collection');
    dict.addQuery('active', true);
    dict.orderBy('element');
    dict.query();

    while (dict.next()) {
        fields.push({
            name: dict.getValue('element'),
            label: dict.getValue('column_label'),
            type: dict.getValue('internal_type'),
            mandatory: dict.getValue('mandatory') === 'true',
            reference: dict.getValue('reference'),
            maxLength: dict.getValue('max_length')
        });
    }

    return fields;
}

Check Field Exists

检查字段是否存在

javascript
// Check if field exists on table (ES5 ONLY!)
function fieldExists(tableName, fieldName) {
    var dict = new GlideRecord('sys_dictionary');
    dict.addQuery('name', tableName);
    dict.addQuery('element', fieldName);
    dict.query();
    return dict.hasNext();
}
javascript
// Check if field exists on table (ES5 ONLY!)
function fieldExists(tableName, fieldName) {
    var dict = new GlideRecord('sys_dictionary');
    dict.addQuery('name', tableName);
    dict.addQuery('element', fieldName);
    dict.query();
    return dict.hasNext();
}

MCP Tool Integration

MCP 工具集成

Available Tools

可用工具

ToolPurpose
snow_query_table
Query dictionary
snow_discover_table_fields
Get field definitions
snow_execute_script_with_output
Test dictionary scripts
snow_find_artifact
Find data policies
工具用途
snow_query_table
查询字典
snow_discover_table_fields
获取字段定义
snow_execute_script_with_output
测试字典脚本
snow_find_artifact
查找数据策略

Example Workflow

示例工作流

javascript
// 1. Get table fields
await snow_discover_table_fields({
    table_name: 'incident'
});

// 2. Query data policies
await snow_query_table({
    table: 'sys_data_policy2',
    query: 'model_table=incident^active=true',
    fields: 'short_description,conditions,apply_to_client'
});

// 3. Check dictionary overrides
await snow_query_table({
    table: 'sys_dictionary_override',
    query: 'name=u_custom_table',
    fields: 'base_element,column_label,mandatory,read_only'
});
javascript
// 1. Get table fields
await snow_discover_table_fields({
    table_name: 'incident'
});

// 2. Query data policies
await snow_query_table({
    table: 'sys_data_policy2',
    query: 'model_table=incident^active=true',
    fields: 'short_description,conditions,apply_to_client'
});

// 3. Check dictionary overrides
await snow_query_table({
    table: 'sys_dictionary_override',
    query: 'name=u_custom_table',
    fields: 'base_element,column_label,mandatory,read_only'
});

Best Practices

最佳实践

  1. Schema Planning - Design before implementation
  2. Field Naming - u_ prefix for custom fields
  3. Data Types - Use appropriate types
  4. Mandatory Fields - Only when truly required
  5. Data Policies - Enforce business rules
  6. Performance - Avoid complex calculated fields
  7. Documentation - Document custom schema
  8. ES5 Only - No modern JavaScript syntax
  1. 表结构规划 - 先设计再实现
  2. 字段命名 - 自定义字段使用u_前缀
  3. 数据类型 - 使用合适的类型
  4. 必填字段 - 仅在真正需要时设置
  5. 数据策略 - 强制执行业务规则
  6. 性能优化 - 避免复杂的计算字段
  7. 文档记录 - 记录自定义表结构
  8. 仅支持ES5 - 禁止使用现代JavaScript语法