
定義リレーション(sys_relationship):参照列なしの関連リスト
ServiceNow のフォームを開くと、下のほうに「関連リスト(Related List)」が並びます。多くは参照フィールド由来です。たとえば User を開くと、その人を Caller(caller_id)に持つ Incident が自動で関連リストに出てきます。では、2つのテーブルの間に直接の参照列が無いのに、関連リストとして並べたいときはどうするのでしょうか。その答えが 定義リレーション(Defined Relationship)、テーブル名で言うと sys_relationship です。
この記事は、参照フィールドと関連リストの基本は知っているが、「参照列が無くても関連リストを出せる仕組み」をテーブルから確認したい管理者・開発者を想定しています。PDI(Zurich / OOTB)で sys_relationship を実際に開き、1行=1つの定義済み関連リストであることを確認します。中核となる3つのフィールド(Applies to / Queries from / Query with)を確認します。基本モードとスクリプトモードの違い、そして「Running Services」という実例も順に確認します。
この記事で分かること
定義リレーションは sys_relationship の1行=1つの「定義された関連リスト」であること
中核はどのテーブルに出すか(Applies to)・どのテーブルを表示するか(Queries from)・どう絞るか(Query with スクリプト)の3つであること
query_with スクリプトでは parent(開いているレコード)と current(表示元テーブル)が使えること
PDI 実機で480件あり、基本モード468件 / スクリプトモード(Advanced)12件という内訳であること
参照フィールド由来の関連リストとの違い=直接の参照列が無くてもスクリプトで動的に関連を引ける点
「Running Services」がCI 関連(cmdb_rel_ci)をたどって機器のサービスを関連リスト化している実例
この記事の内容は ServiceNow の PDI(Personal Developer Instance)Zurich(ズーリッヒ)リリースの OOTB(初期設定)で確認した個人メモです。本番環境やカスタマイズ済み環境では、フィールド・選択肢・関連の内容が異なる場合があります。
定義リレーション(sys_relationship)とは
定義リレーションとは、「あるテーブルのフォームに、別のテーブルのレコードを関連リストとして出す」その定義を1件=1レコードで持ったものです。メニューでは System Definition > Relationships からたどれます。下の実画面は、その1件をフォームで開いたものです。

このレコードは Name に Running Services が入っています。Applies to table に cmdb_ci_computer、Queries from table に cmdb_ci_service も入っています。つまり「Computer(機器)の CI フォームに、その機器が使われている Service の CI を関連リストとして出す」という定義です。関連リストの中身は、参照列ではなく Query with のスクリプトで決まります。
PDI(Zurich / OOTB)の sys_relationship には、すでに 480件の定義が入っていました。
中核は3つ:Applies to / Queries from / Query with
sys_relationship のフィールドは固有で12件ありますが、関連リストの形を決めるのは次の3つです。

basic_apply_to(Applies to table) … この関連リストを出す側のテーブル。例では cmdb_ci_computer。
basic_query_from(Queries from table) … 関連リストに表示するレコードのテーブル。例では cmdb_ci_service。
query_with(Query with) … 表示するレコードを絞る条件スクリプト。ここで parent(フォームで開いているレコード) と current(表示元テーブルの GlideRecord) が使えます。

フィールド定義は次のURLで確認できます(先頭の <YourInstance> は自分のインスタンスに置き換えてください)。
https://<YourInstance>/sys_dictionary_list.do?sysparm_query=name=sys_relationship^elementISNOTEMPTY
参照フィールド由来の関連リストとの違い
User フォームの Incident のように、参照フィールド由来の関連リストは「参照列の値が一致する行」を自動で並べます。片側のテーブルに reference 列があることが前提です(参照の仕組みは参照フィールドと参照修飾子の記事を参照)。

一方、定義リレーションは 直接の参照列が無くても、Query with のスクリプトで関連を自由に引けるのが強みです。冒頭の Running Services がまさにそれで、cmdb_ci_service には「どの Computer で使われているか」を指す参照列がありません。それでも関連リストとして出せるのは、スクリプトの中で別のテーブルをたどっているからです。両者の違いを整理すると次の通りです。

ServiceNow で関連リストがどう並ぶかという全体像はリストレイアウトと関連リストの記事で扱っています。定義リレーションは、その関連リストの「源」のひとつだと考えると位置づけが分かりやすくなります。
実例:Running Services が CI 関連をたどる流れ
Running Services の Query with スクリプトは、おおむね次の処理をしています。
var serverId = parent.sys_id; // 開いている Computer
var relCI = new GlideRecord('cmdb_rel_ci');
relCI.addQuery('child', serverId); // この機器を child に持つ CI 関連
relCI.addQuery('type.child_descriptor', 'Used by');
relCI.query();
var ids = [];
while (relCI.next()) ids.push(relCI.parent + '');
current.addQuery('sys_id', 'IN', ids.join(',')); // その親(=サービス)だけ表示
つまり、Computer のフォームを開くと、その機器を child に持つ CI 関連(cmdb_rel_ci)を「Used by」でたどります。その親であるサービス群だけを cmdb_ci_service から拾って、関連リストに並べる流れです。CI 関連そのものの構造はCI 関連(cmdb_rel_ci)の記事で扱っています。参照フィールドでは決して表せない、他テーブルを横断する関連リストが、たった1件の定義リレーションで実現できているわけです。
基本モードとスクリプトモード(Advanced)
定義リレーションには2つのモードがあります。実機の480件のうち、基本モード(Advanced=false)が468件、スクリプトモード(Advanced=true)が12件でした。一覧は次のURLで確認できます。
https://<YourInstance>/sys_relationship_list.do?sysparm_query=ORDERBYname
基本モードは、Applies to table / Queries from table をテーブル名で直接指定します。これに対しスクリプトモードは、Advanced にチェックを入れると2つの欄が Apply to / Query from というスクリプトに変わります。どのテーブルに出すか・どのテーブルから引くかを動的に決められるようになります。OOTB の代表例が Metrics です。

Metrics は Apply to スクリプトで「metric_definition にアクティブな定義があるテーブルすべて」に answer=true を返します。Query with では current.addQuery('table', parent.getRecordClassName()) を使います。これは開いているレコードのテーブル名と sys_id で metric_instance を絞る処理です。だから Incident でも Change でも、メトリクス定義さえあれば同じ Metrics 関連リストが出るわけです。スクリプトモードの代表例を整理すると次の通りです。

同じくスクリプトモードの Audit History は、GlideAuditor で「監査が有効なテーブルすべて」に出し、sys_history_line を表示します。どんなテーブルでも Activity の隣に監査履歴が出せるのは、この1件の定義によるものです。

なお、Apply to / Query from / Query with スクリプトの内部評価順序やキャッシュは、今回の検証範囲外です。関連リストをフォームに並べる際の sys_ui_related_list 連携の細部も、検証範囲外です。
実機で確認するときに見るべきURL
最後に、今回見た画面を自分のインスタンスで開くためのURLをまとめます(<YourInstance> は置き換えてください)。
# 定義リレーションの一覧
https://<YourInstance>/sys_relationship_list.do?sysparm_query=ORDERBYname
# スクリプトモード(Advanced)だけ
https://<YourInstance>/sys_relationship_list.do?sysparm_query=advanced=true
# sys_relationship のフィールド定義
https://<YourInstance>/sys_dictionary_list.do?sysparm_query=name=sys_relationship^elementISNOTEMPTY公式の手順は ServiceNow ドキュメントの Create defined related lists(Zurich) でも説明されています。
まとめ
定義リレーションは sys_relationship の1行=1つの「定義された関連リスト」です。
中核は Applies to table(出す先)/ Queries from table(引く元)/ Query with(絞り条件スクリプト)の3つです。スクリプトでは parent(開いている行)と current(表示元)が使えます。
PDI 実機では480件(基本モード468 / スクリプトモード12)です。
参照フィールド由来の関連リストとの違いは、直接の参照列が無くてもスクリプトで動的に関連を引ける点です。Running Services は cmdb_rel_ci をたどって機器のサービスを関連リスト化していました。
スクリプトモード(Advanced)では Apply to / Query from もスクリプトになります。テーブルを横断して同じ関連リストを出せます(Metrics・Audit History など)。
定義リレーションが分かると、「テーブル定義まわり」が関連リストという視点でひとつにつながって見えてきます。具体的には、テーブルとフィールド(sys_db_object / sys_dictionary)・参照フィールドと参照修飾子・リストレイアウトと関連リストです。