メインコンテンツへスキップ
見出し画像

ServiceNowのフィールド設定はどこに保存される? sys_dictionaryを実機で読む


    必須にしたはずの項目が、なぜかフォームで必須になっていない。ServiceNowでフィールドの型や桁数、参照先を確認したいとき、どこを見ればよいか迷うこともあります。テーブルそのものの定義はsys_db_objectに、フィールド(列)の定義はsys_dictionaryに、1件ずつレコードとして記録されています。Zurich PDIでincidentのフィールドを実際に開き、型・参照先・必須設定がどこにどう記録されているかを確認しました。

    検証環境:Zurich PDI / OOTB / 2026-08-08 確認


    結論:テーブルは sys_db_object、フィールドは sys_dictionary の1行


    画像

    このフォームの各項目は、どこかに記録されています。どこにどう記録されているかを1枚で整理すると次のようになります。

    • ServiceNowの「テーブル」はsys_db_objectに1テーブル=1レコードで定義されます。今回のPDIでは6,317件でした。

    • 「フィールド」を持つsys_dictionaryには2種類の行が混ざっています。elementが空の行はテーブル自身を表す行(6,299件)、elementに値がある行が実際のフィールド定義(148,209件)です。合計154,508件のうち、この記事で扱う「フィールド定義」は後者だけです。

    • 継承関係はsys_db_objectのsuper_classフィールドに出ます。子テーブルのsys_dictionaryには親から継承したフィールドは載りません。incident自身の固有フィールドは25件ですが、親のtaskが70件を持つため、フォームに並ぶ項目はもっと多くなります。


    画像

    図の色は4種類の意味に固定しています。濃紺は起点のsys_db_object、水色はnameで結ばれるsys_dictionary側、灰色はelementが空の行(テーブル自身)、緑はelementに値がある行(実フィールド)です。


    テーブルの定義はどこにある? sys_db_object を実機で開く

    ServiceNowでは、テーブルを作るとsys_db_objectに1レコード増えます。incidentテーブルのレコードを開くと、name・label・super_classにそれぞれ値が入っていました。


    画像

    incidentのsys_db_objectレコードに入っていた値

    • name=incident(クエリやスクリプトで使う内部名)

    • label=Incident(画面に出る表示名)

    • super_class=Task(継承元。「incidentはtaskを継承する」の実体は、この1列だけです)

    • is_extendable=false(incidentはこれ以上継承できない末端のテーブル)

    sys_db_object の主なフィールド

    sys_db_objectの固有フィールドは27件あり、主なものは次のとおりです。


    画像

    number_refは自動採番設定(sys_number)への参照です。INC0001234のような番号がどう決まるかは、レコード採番(sys_number):INC番号の決まり方で確認しています。sys_class_code・sys_class_pathはCMDBのような深いクラス階層を持つテーブルで、親までの経路を表す内部値です。

    is_extendableも実務で見る機会がある列です。incidentはfalseでした。これは「incidentからさらに継承したテーブルは作れない」という意味です。自分で新しいテーブルを作り、既存テーブルを親にしたい場合は、先に親候補のis_extendableを確認しておくと、継承できない設計に途中で気づくような手戻りを避けられます。


    incidentの項目が sys_dictionary にはなぜ25件しかない?(継承の実測)

    incidentのフォームには数十の項目が並びますが、sys_dictionaryをname=incidentで絞ると25件しかありません。理由は継承です。子テーブルのsys_dictionaryには、親テーブルの固有フィールドが載りません。incidentが継承するtaskは、自分の固有フィールドを70件持っています。フォームに見えている項目は、incidentの25件とtaskの70件を合わせたものです。


    画像

    taskを直接継承するテーブル(super_class.name=task)は49件ありました。ITSMでよく使うincident・problem・change_request・sc_req_itemは、いずれもこの49件の中に含まれます。


    画像

    super_classの値は、テーブルによって扱いが異なります。


    画像
    • incident(Incident)・problem(Problem)・change_request(Change Request)・sc_req_item(Requested Item)→ super_class=task

    • cmdb_ci(Configuration Item)→ super_class=cmdb(Base Configuration Item)

    • kb_knowledge(Knowledge)→ super_class=空(継承なし)

    task系の4テーブルはtaskを継承する浅い継承です。cmdb_ciはcmdbを継承したうえで、さらに深いクラス階層を持ちます。kb_knowledgeは継承を持たない独立系です。あるテーブルが何を継承しているかを知りたいときは、super_classの値を見るだけで判定できます。

    固有フィールド数も合わせて数えると、継承の深さとの関係が見えてきます。incident 25・problem 31・change_request 38・sc_req_item 17に対し、taskを継承しないkb_knowledgeは58です。継承なしのkb_knowledgeは、共通項目まで自分のsys_dictionaryに持つ必要があるため、固有フィールド数がtask系よりも多くなっています。深いクラス階層を持つcmdb_ciはさらに多く、81でした。


    super_classでは説明しきれない上書きもある

    super_classは「どのテーブルから継承するか」を示す列です。継承したフィールドそのものの中身までは変えません。ただし、親テーブルの定義を子テーブルだけで上書きしたいケースもあります。たとえば「priorityの既定値をincidentだけ変えたい」「参照修飾子をchange_requestだけ絞りたい」といった要望です。こうした子テーブル限定の上書きは、sys_dictionary_overrideという別のテーブルが担っています。super_classをたどるだけでは見えない例外があることは、継承を扱ううえで覚えておくとよい点です。


    フィールドの型・参照先・必須はどの列に出る?(internal_type / reference / mandatory)

    incidentの固有フィールドをsys_dictionaryで一覧すると、element・internal_type・reference・default_valueなどの列が並びます。


    画像

    caller_idはinternal_type=Reference、reference=Userでした。「Reference型でsys_userを参照する」は、internal_typeがreferenceで、reference列がsys_userを指している、という意味です。default_valueにはjavascript:incidentGetCaller();というスクリプトが入っており、単純な固定値だけでなく、スクリプトで既定値を計算するフィールドもあることが分かります。incident自身のReference型フィールドは7件でした。


    画像

    sys_dictionary の主なフィールド

    sys_dictionaryの固有フィールドは58件あり、主なものは次のとおりです。


    画像

    column_labelは画面に出るラベルの入り口ですが、実際の表示文言(多言語対応やヒント文)は別のsys_documentationというテーブルが持っています。この分担はフォームのラベルはどこから出るか(sys_documentation)で確認しました。choiceは選択肢の扱いを表す制御値で、選択肢そのものの実体は選択肢Choice(sys_choice):ドロップダウンの中身という別テーブルに入ります。


    フィールドの型は何が多い? internal_type の分布を数える

    sys_dictionaryの148,209件(elementに値がある行)を型ごとに数えると、stringとreferenceが中心でした。internal_type自体はsys_glide_objectへのReference型で、フィールド型そのものが1つのテーブルに定義されています。


    画像


    画像

    上位6型(string / reference / glide_date_time / integer / boolean / GUID)だけで全体の約83%を占めます。表の12型まで広げると約92%です。ServiceNowのフィールドの大半は、文字列か、別テーブルへの参照か、日時・数値・真偽のいずれかだと分かります。internal_type自体もsys_glide_objectへのReference型です。フィールド型の一覧そのものが1つのテーブルで管理されている点は、フィールドの「型」の正体(sys_glide_object)で確認しました。


    実機で気づいたこと

    incidentのCallerとShort descriptionは、フォーム上で赤いアスタリスク付きの必須項目に見えます。ところがsys_dictionaryでcaller_idとshort_descriptionのmandatory列を見ると、どちらもfalseでした。意外でした。incident自身の固有フィールド25件・taskの固有フィールド70件のうち、mandatory=trueは1件もありません。原因を辿るとsys_ui_policy_actionに行き着きました。caller_idを必須にするUI Policy Actionが1件、short_descriptionを必須にするものが7件登録されていました。フォームの必須表示は、sys_dictionaryではなくUI Policy側が作っていたことになります。「必須にしたはずなのに必須になっていない」という悩みは、まずsys_dictionaryのmandatory列だけでなく、UI Policyも合わせて確認する必要があると分かります。mandatory列そのものが使われていないわけではありません。sys_dictionary全体の148,209件(elementに値がある行)のうち、mandatory=trueは13,243件、約9%ありました。incidentやtaskのように、フォーム上の必須表示をUI Policyに任せているテーブルもあれば、mandatory列に直接trueを持たせているテーブルもあるということです。

    incident自身の固有フィールドが25件しかないことも、実際に数えてみるまで意識していませんでした。少なく感じました。フォームに10個以上の項目が並んでいても、その多くはtask側の70件から来ています。1つのテーブルの「全項目」を知りたいときは、そのテーブル単体のsys_dictionaryだけでは足りず、super_classをたどって親のフィールドも合わせて見る必要があります。

    sys_dictionaryの総数は、2026-06-20の152,744件から2026-08-08には154,508件に増えていました。約7週間で1,764件、task直接子も48件から49件に増えています。カスタマイズを加えていないPDIでも、パッチや自動更新のたびに件数は動きます。OOTBの数値は固定ではありません。確認した時点のスナップショットとして扱う方が安全です。


    実務では何に使える? 新しいフィールドを追加する前に確認すること

    「change_requestにカスタムフィールドを追加してほしい」という依頼を受けたときを考えます。フォームエディタで新規フィールドを作るより先に、sys_dictionaryを確認しておくと手戻りが減ります。同じ役割のフィールドがすでに存在していないか、親テーブル(この場合はtask)に近い名前のフィールドがないかを、追加の前に見ておくという使い方です。新しくフィールドを追加する前、あるいは既存フィールドの挙動を調べる前に見るポイントは、実質3つに絞れます。

    • element名の重複がないか … sys_dictionaryをname=対象テーブルで絞り、同じ内部名がすでに使われていないか確認します。

    • 型・桁数・参照先が要件に合うか … internal_type・max_length・reference列を見て、Integration用のフィールドなら文字数やデータ型が連携先と一致するかを確認します。

    • 必須に見える動きはmandatory以外も疑う … 「保存できない」「必須マークが消えない」といった相談では、sys_dictionaryのmandatoryがfalseでも、UI PolicyやClient Scriptが必須化している場合があります。

    カスタマイズ前のチェック手順

    1. sys_dictionary_list.do?sysparm_query=name=<テーブル名>^elementISNOTEMPTY で対象テーブルの固有フィールドを一覧する

    2. super_classをたどり、親テーブルの固有フィールドも合わせて確認する(継承したフィールドは子のsys_dictionaryには出ない)

    3. mandatory・default_value・reference列で既存の設定を確認する

    4. フォーム上の見た目と食い違う場合は、sys_ui_policy_actionを対象フィールドで絞って確認する

    この4手順を踏むと、フィールド1つの「定義上の設定」と「フォームでの見え方」を分けて調べられます。両者が一致しないこと自体は珍しくありません。今回のcaller_id・short_descriptionのように、定義とフォームの見え方が食い違うケースがあると分かっていれば、調査の当たりを付けやすくなります。


    さらに詳しく知りたい人へ


    まとめ

    テーブルの定義とフィールドの定義は、それぞれsys_db_objectとsys_dictionaryという1つのテーブルに集約されています。継承はsuper_class、型と参照先はinternal_typeとreference、必須はmandatoryという列を見れば、フィールド1つの仕組みは追えます。ただしmandatoryだけでは「フォーム上で必須に見えるかどうか」を説明しきれません。今回のincidentのように、UI Policyが必須表示を後から足しているケースがあるためです。次にフィールドの挙動を調べるときは、sys_dictionaryとsys_ui_policy_actionの両方を見る習慣をつけると、原因の切り分けが早くなります。テーブルとフィールドの定義そのものは、ServiceNowのほぼすべての機能が土台にしている仕組みです。ここで押さえた読み方は、UI ActionやBusiness Ruleなど他の設定テーブルを読むときにもそのまま使えます。

    用語

    • PDI … Personal Developer Instance(無料の検証用インスタンス)

    • OOTB … Out of the Box(初期設定のまま)

    • sys_db_object … テーブルそのものの定義テーブル(Tables)

    • sys_dictionary … フィールド(列)の定義テーブル(Dictionary)

    • super_class … 継承元テーブルを指すReferenceフィールド(=extends)

    • internal_type … フィールドの型(string / reference / integerなど)

    • element … sys_dictionary上のフィールドの内部名(空=テーブル自身の行)

    実機で調べるときに開いたURL

    • sys_db_object_list.do?sysparm_query=name=incident … incidentのテーブル定義

    • sys_db_object_list.do?sysparm_query=super_class.name=task … taskの直接子

    • sys_dictionary_list.do?sysparm_query=name=incident^elementISNOTEMPTY … incidentの固有フィールド

    • sys_dictionary_list.do?sysparm_query=name=incident^internal_type=reference … incidentのReference型フィールド


    参考リンク


    検証環境と未検証範囲

    確認した範囲(PDI/Zurich/2026-08-08 確認):

    • sys_db_object/sys_dictionaryの固有フィールド数(27/58)、テーブル定義総数(6,317)、フィールド定義総数(154,508)

    • sys_dictionaryのelementが空の行(6,299)とelementに値がある行(148,209)の内訳

    • task直接子(49)、incident固有フィールド(25)・task固有フィールド(70)

    • incident・problem・change_request・sc_req_item・cmdb_ci・kb_knowledgeのsuper_class

    • internal_typeの分布(上位12型・全体の約92%)

    • incidentのcaller_id・short_descriptionのmandatory値と、対応するsys_ui_policy_actionの件数

    • sys_dictionary全体のmandatory=true件数(148,209件中13,243件)

    確認していない範囲:

    • choice列の制御値の網羅的な意味、各internal_typeの内部実装、attributesの全パラメータ

    • collection行(element空)の細部、テーブル定義変更時のスキーマ同期や物理列(sys_storage_alias)の挙動

    • ドメイン分離やスコープアプリケーションによる差異

    • gsftSubmitやClient Scriptなど、UI Policy以外が必須表示に関与するケースの網羅

    件数は2026-08-08時点の値です。本番環境やカスタマイズ済み環境では、テーブル数・フィールド数・型の分布・UI Policyの構成が異なります。

     
     
    ServiceNowのPDI(Personal Developer Instance)を実機で観察して、Noteに記事を書いています 実装・運用・教育の現場視点で淡々と記録中です リクエストがあればその記事も書きます 個人の観察日記です

    あなたへのおすすめ