关于 data-policies
面向 ServiceNow 开发人员的字典与数据策略指南,介绍字段和表结构定义,以及用于维护数据完整性的策略规则。提供 ES5 示例、模式查询方法和相关 MCP 工具。
主要功能
- 01管理表与字段定义
- 02配置字典覆盖和字段选项
- 03创建数据策略及规则
- 04校验字段并查询模式
- 05介绍相关 MCP 工具
适用场景
- 01为自定义表规划字段结构
- 02要求记录满足业务数据规则
- 03检查表字段或策略配置
MCP 相关
列出可用于字典和数据策略工作的 ServiceNow MCP 工具:snow_query_table、snow_discover_table_fields 和 snow_execute_script,并示范查询字段定义与数据策略。
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ serac-labs/ serac --skill data-policies安装后在 Claude Code 中输入/data-policies确认已加载。
详细介绍
ServiceNow 的数据策略与字典
数据策略用于强制执行数据完整性规则。字典用于控制架构和字段行为。
架构
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
主要表
| 表 | 用途 |
|---|---|
sys_dictionary | 字段定义 |
sys_dictionary_override | 作用域覆盖 |
sys_data_policy2 | 数据策略 |
sys_data_policy_rule | 策略规则 |
sys_db_object | 表定义 |
字典管理(ES5)
创建表
// 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 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()
字段类型
// 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 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" },
])
字典覆盖(ES5)
创建覆盖
// 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()
数据策略(ES5)
创建数据策略
// 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 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()
}
复杂数据策略
// 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)
字段验证(ES5)
字典属性验证
// 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
}
脚本验证
// 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
})()
架构查询(ES5)
获取表字段
// 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 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 工具集成
可用工具
| 工具 | 用途 |
|---|---|
snow_query_table | 查询字典和数据策略 |
snow_discover_table_fields | 获取字段定义 |
snow_execute_script | 测试字典脚本 |
示例工作流
// 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",
})
最佳实践
- 架构规划 - 实施前先进行设计
- 字段命名 - 自定义字段使用 u_ 前缀
- 数据类型 - 使用恰当的类型
- 必填字段 - 仅在确实需要时设置
- 数据策略 - 强制执行业务规则
- 性能 - 避免使用复杂的计算字段
- 文档 - 记录自定义架构
- 仅限 ES5 - 不使用现代 JavaScript 语法
评论
支持 Markdown