
ServiceNowで複数テーブルを1つの一覧にまとめるには? Database View(sys_db_view)を実機で確認する
Change Requestとその影響を受けたCIのように、別々のテーブルに入っている情報を1つの一覧やレポートにまとめたい。そんな場面はよくあります。ServiceNowには、複数テーブルを結合して1つの仮想テーブルにするDatabase View(sys_db_view)という仕組みが用意されています。Zurich PDIには108件のDatabase Viewが登録されていて、そのうちの1つを実際に開き、一覧として表示できるか、レポートのソースに指定できるかまで実機で確認しました。
検証環境:Zurich PDI / OOTB / 2026-08-09 確認
結論:Database Viewは複数テーブルを結合して1つの仮想テーブルにする仕組み
先に全体像です。
sys_db_viewは108件登録されています。1件が「1つのDatabase View」に対応します。
各Database Viewが結合しているテーブルの定義はsys_db_view_tableに309件あり、1つのビューは平均2.86テーブルを結合しています。
Database Viewは、通常のテーブルと同じように一覧(list.do)でもレポート・Data Visualizationのソースとしても開けました。ここが関連リストや参照フィールドとの一番の違いです。
実例は1つに絞ります。Service Portalのページとウィジェットを結びつけるsp_page_widgetsというDatabase Viewを選び、最後まで実機で追いかけます。
公式ドキュメントはDatabase Viewをどう説明しているか
実機を見る前に、公式ドキュメントWork with database viewsの説明を押さえておきます。ここでの記述はPDIで実測したものではなく、公式仕様として書かれている内容です。
レポート専用の結合として定義されている
ドキュメントには「database views define table joins specifically for reporting(レポートのために定義されたテーブル結合である)」とあります。複数テーブルのデータを1つのレポート可能なソースにまとめる目的で作られた仕組みで、レポート作成権限を持つユーザーなら誰でもデータソースとして使えると説明されています。カスタムテーブルを新設せずに集計できる点がメリットとして挙げられていました。
一覧の更新はできない・読み取り専用
「data in database views is read-only(データは読み取り専用)」とも明記されています。Database Viewの一覧からレコードを新規作成したり更新したりはできない、ということです。後述しますが、Table APIで取得したsys_idが通常と違う形をしていたのも、この読み取り専用という性質と無関係ではなさそうです。
パフォーマンスとACLの注意点
結合するテーブル数・件数が増えるほど性能への影響が大きくなります。where句にはインデックスの張られたフィールドを使うことが推奨されていました。ACLについては、Database View自体にACLが設定されていればそちらが優先されます。設定がなければ、結合元テーブルのACLがそのまま適用されると説明されていました。加えて、Table Rotation(テーブルの世代分割)の対象テーブルにはDatabase Viewを作成できません。クローン時のデータ保全対象にもならず、FTPエクスポートにも含まれないという制約もあります。テーブル結合の作り方自体はJoining tablesにまとまっていました。OR条件を使いたい場合はUse disjunctions in complex queriesを参照します。
sp_page_widgetsを開くと6テーブル分の結合定義が1画面に並ぶ
ここから実機です。まず、Database Viewのレコード自体がどう見えるかを確認します。sys_db_viewは1件ごとにname・label・descriptionという普通のテーブル定義のような項目を持っていました。それに加えて、フォームの下に「View Tables」という関連リストが埋め込まれていて、そこに結合対象のテーブルが並びます。

Descriptionには「DB view to retrieve all widgets across all service portal pages」とあります。日本語にすると「全ポータルページのウィジェットを取得するDBビュー」という意味です。下の関連リストを見ると、sp_pageから始まってsp_container→sp_row→sp_column→sp_instance→sp_widgetまで、6つのテーブルが結合されていました。Service Portalの画面構成を扱った既存記事では、1つのページが7つのテーブルの組み合わせで成り立っていることを確認しました。そのうちの6テーブルを、Database Viewが1本のクエリで結合してくれるわけです。
sys_db_viewとsys_db_view_tableはどう対応しているのか
sys_db_viewの一覧を開くと、108件のDatabase Viewが並びます。

一覧の下には全部で108件という件数が表示されていて、これが本文で使っている数字の出どころです。ここで、108件と309件という数字の中身をもう少し見ておきます。
108件のビューが結合しているテーブル数の分布
sys_db_view_tableをビューごとに集計すると、次のような分布でした。

2テーブルの結合がもっとも多く51件、3テーブルが33件と続きます。sp_page_widgetsのような6テーブル結合は4件しかなく、最大はlicensable_tableという8テーブルを結合したビューでした(ラベル未設定で用途は未確認です)。Database Viewの大半は、2〜3テーブルをつなぐ比較的シンプルな使われ方だと分かります。
sys_db_view_tableだけを単独の一覧として開くと、同じ内容を「Table / Order / Variable prefix / Where clause」という列で確認できます。

Variable prefixがフィールド名の衝突を防ぐ
ここで注目したいのがVariable prefixという列です。1つのビューに複数テーブルを結合すると、どのテーブルもsys_idのような同名フィールドを持つため、そのままでは列名が衝突します。そこでDatabase Viewは、テーブルごとにpg・con・row・col・inst・widという接頭辞を振り、pg_sys_idやwid_nameのように「接頭辞_フィールド名」でアクセスできるようにしていました。Where clauseのcon_sp_page = pg_sys_idという条件も、この接頭辞を使い「コンテナのsp_pageフィールドと、ページのsys_idが一致するものを結合する」という意味になります。
Catalog Categoriesページの5つのウィジェットが1回のクエリで返ってくる
結合の仕組みが分かったところで、実際にジョインした結果を最後まで追ってみます。sp_page_widgetsが結合している6テーブルの流れを図にすると、次のようになります。

起点はsp_page(ページ)です。そこに載るsp_container(コンテナ)、その中のsp_row(行)、さらに中のsp_column(列)と続きます。続いて配置情報を持つsp_instanceを経て、最後は実体であるsp_widget(ウィジェット定義)に至ります。6段階のwhere_clauseをたどって、1つの行にまとまる仕組みです。
これを実際にAPIで叩いてみます。pg_title(ページタイトル)とwid_name(ウィジェット名)のような列を指定するだけです。それだけで、6テーブルをまたいだ結果が1件ずつ返ってきました。試しにCatalog Categoriesというページで絞り込みます。ヒットしたのはTypeahead Search・breadcrumbs・SC Categories・SC Category Page・SC Scroll to topの5つです。いずれも1行ずつ返ってきました。これを一覧画面で開いた様子が次の画像です。

パンくずに「Title = Catalog Categories」と出ているとおり、pg_titleという結合先のフィールドが、そのまま検索条件として使えていました。1つの親ページに複数のウィジェットが紐づく、という関係を、sp_pageとsp_widgetを別々に開いて手でつなぎ合わせなくても、この1つのビューを見るだけで分かります。
Database Viewは一覧としてもレポートのソースとしても開けた
ここまでは絞り込んだ状態を見てきましたが、絞り込まずに開くとどうなるかも確認しておきます。全体は373件でした。

ここで少し気になったのが、既定で表示される列です。CSS class・Order・Semantic tag・Size - md/lg/sm/xsのような列が並んでいました。ページ名やウィジェット名ではなく、6テーブルのうちsp_columnが持つフィールドがそのまま出ているようです。List Layoutが未設定のDatabase Viewを開くと、結合したどれか1つのテーブルの列が既定表示になるようでした。狙った列を見るには、自分でPersonalize Listからpg_titleやwid_nameを追加する必要があります。
もう1つ確認したかったのが、「一覧として開けるだけでなく、レポートのソースに指定できるか」という点です。このPDIでは旧来のレポートビルダー($reportv2.do)はすでに廃止されていました。いまはPlatform Analyticsワークスペースの「Data Visualization」からグラフを作ります。新規のVisualizationを作る画面で「Add data source」を開き、検索欄に「Page Widget」と入力してみました。
![Data Visualization workspaceのAdd data sourceダイアログ。検索欄にPage Widgetと入力すると、Tablesカテゴリの下にService Portal - Page Widget Mapping [sp_pag...]という候補が表示されている](assets/sn-09-dataviz-source-search.png)
「Tables」というカテゴリの下に、sp_page_widgetsのラベルである「Service Portal - Page Widget Mapping」が候補として出てきました。普通のテーブルを探すのと同じ検索窓に、Database Viewも並んでいます。実際にグラフを作って保存するところまでは行っていませんが、データソースとして選択できることは確認できました。先の公式ドキュメントにあった「レポート作成権限を持つユーザーなら誰でもデータソースにできる」という説明と、この画面の見え方は一致していました。
Change RequestとCIをまとめるcmdb_task_chgも同じ仕組みだった
冒頭で例に挙げた「Change Requestとその影響を受けたCI」も、実はcmdb_task_chg(ラベルはChange Request Affected CI)というDatabase Viewでした。cmdb_ci・task_ci・change_requestの3テーブルを結合していて、全体で66件です。

一方、Incidentのフォーム下部にある「Affected CIs」という関連リストは、これとは別物です。以前別の記事でincidentの関連リストを調べたときに分かったことですが、あちらはtask_ciという単一テーブルへの関連リストで、列もci_itemとtaskの2つしか持っていません。しかも表示されるのは、開いている1件のIncidentに紐づくCIだけです。同じ「Affected CI」という言葉が使われていても、cmdb_task_chgはChange RequestとCIの組み合わせを全件横断で一覧・レポートできる仕組みです。対してIncidentの関連リストは、1件のレコードに紐づく子だけを見るための仕組みという、はっきりした違いがあります。
関連リストや参照フィールドで足りるときはDatabase Viewを使わない
ここまでの実機確認を踏まえると、複数テーブルの情報をまとめる手段は少なくとも3つあり、それぞれ向き不向きがあります。

「1件のレコードを開いたときに、その子を確認・追加したい」だけなら関連リストで十分です。「参照先の1つの値をそのまま列に出したい」だけなら参照フィールドで済みます。Database Viewを新規に作る必要が出てくるのは、条件に合う全レコードを横断して、複数テーブルの列を1行にまとめて集計・分析したいときです。たとえば「ページごとに何個のウィジェットが配置されているか」を全ページ分まとめて見たいとします。sp_pageとsp_widgetを個別に開いて手で数えるより、sp_page_widgetsを使ったほうが早く済みます。1件のIncidentのAffected CIsを確認するだけなら、Database Viewを新しく作るのはやり過ぎです。
設計を検討する順番としては、まず参照フィールドで足りないかを疑います。次に「1件の親に紐づく子を見たいだけか」を確認して、関連リストで済むかを判断します。それでも「全レコードを横断して集計したい」という要件が残ったときに、初めてDatabase Viewを検討する、という流れが実務向きだと感じました。今回見たsp_page_widgetsとcmdb_task_chgのwhere_clauseは、どちらもcon_sp_page = pg_sys_idのような単純な等号条件だけで構成されていました。公式ドキュメントにはOR条件(disjunction)を使う手順も載っているので、もっと複雑な条件も組めるようですが、そこはPDIでは確認していません。
実機で気づいたこと
実際にDatabase Viewを触ってみました。想定と違った点は3つです。
1つ目は、既定の一覧の列が、結合結果を代表する列にはなっていなかったことです。sp_page_widgetsではsp_columnの列(CSS classなど)が、何の説明もなく既定表示になっていました。cmdb_task_chgのほうも同様で、change_requestの承認系の列(Active、Approvalなど)が既定表示になります。どちらも「起点になっている先頭のテーブル」でも「最後に結合されたテーブル」でもなく、規則性は見つけられませんでした。Database Viewを一覧として使うときは、まずPersonalize Listで見たい列を選び直す作業が必須だと分かります。
2つ目は、Table APIで列を指定せずに取得すると、sys_idが__ENC__から始まる長い文字列になっていたことです。通常のテーブルのsys_idは32桁の英数字です。Database Viewは複数テーブルの行を結合した仮想的な1行なので、単一のsys_idでは表せません。複合キーを符号化していると見られますが、詳しい形式までは確認していません。公式ドキュメントが「データは読み取り専用」と明記していたことを踏まえると、更新用の単純なキーを持たせる必要がない設計なのだろうと納得しました。
3つ目は、sys_db_view.descriptionという一見地味なフィールドに、レポート用途がはっきり書かれていたことです。incident_metricのdescriptionは「creating a view that can be reported on」でした。change_request_slaのほうも「to report on things like…」という書き出しです。個々のビューのdescriptionと、公式ドキュメントの説明文は、同じ方向を向いていました。ドキュメント側の表現は「database views define table joins specifically for reporting」です。単なる結合済みテーブルという以上に、レポート基盤の一部として設計されている点がうかがえます。実機と公式ドキュメントの両方から、同じ結論を確認できたことになります。
よくある質問
Q1. Database Viewの一覧からレコードを追加・編集できますか
できません。公式ドキュメントに「データは読み取り専用」と明記されています。今回開いたsp_page_widgets一覧・cmdb_task_chg一覧でも、参照先のレコードを開くリンクはありましたが、Database View自身への新規作成は試していません。編集したい場合は、結合元の個別テーブル(sp_pageやsp_widgetなど)を直接開く必要があります。
Q2. 既存のテーブルにDatabase Viewを追加すると、パフォーマンスに影響しますか
公式ドキュメントには、結合するテーブル数・件数が増えるほど性能への影響が大きくなるとあり、where句にはインデックスの張られたフィールドを使うことが推奨されていました。今回のPDIはデータ量が少なく、性能影響そのものは確認していません。
Q3. sp_page_widgetsのように6テーブルを結合するのは珍しいのでしょうか
今回確認した範囲では珍しいほうです。108件のDatabase Viewのうち、6テーブル結合は4件だけで、もっとも多いのは2テーブル結合(51件)でした。3テーブル以下で全体の8割弱を占めています。
Q4. Database Viewとレポート(sys_report)は同じものですか
別物です。Database Viewは「複数テーブルを結合した1つの仮想テーブル」で、レポートはそのテーブル(Database Viewを含む)を元に作るグラフや集計です。Database Viewを1つ作っておけば、それを元にしたレポートは複数作れます。
用語
Database View(sys_db_view) … 複数テーブルを結合し、1つの仮想テーブルとして一覧・レポートから参照できるようにする仕組み。データは読み取り専用。
sys_db_view_table … Database Viewが結合するテーブルの定義。1テーブルにつき1レコードで、Order(結合順)・Variable prefix(列名の接頭辞)・Where clause(結合条件)を持つ。
Variable prefix … 結合した各テーブルのフィールド名が衝突しないように付ける接頭辞。例: pg_sys_idのpg部分。
関連リスト(Related List) … フォーム下部に表示される、開いている1件のレコードに紐づく子レコードの一覧。
参照フィールド(Reference) … 別テーブルの1レコードを指し示すフィールド型。参照先の値を1列として表示できる。
自分の環境で確認するときのURL
/sys_db_view_list.do … Database View(sys_db_view)の一覧
/sys_db_view_table_list.do?sysparm_query=view.name=<ビュー名> … 指定したビューが結合しているテーブルの一覧
/<ビュー名>_list.do(例: /sp_page_widgets_list.do) … Database Viewをそのまま一覧として開く
/now/platform-analytics-workspace/data-visualization-library … レポート・グラフ作成の入口(Data Visualization)
参考リンク
関連記事
検証環境・検証範囲
検証環境はZurich PDI(OOTB、2026-08-09確認)です。REST API(読み取り専用)とPDI画面から、sys_db_view(108件)とsys_db_view_table(309件)の総件数を確認しました。sp_page_widgets(6テーブル結合・373件)とcmdb_task_chg(3テーブル結合・66件)の構造も見ました。両ビューとも、Table API・list.do・Data Visualizationのデータソース検索から参照できることを合わせて確認しています。
読み取り専用・パフォーマンス・ACLの優先順位・OR条件(disjunction)・Table Rotation対象外・ライセンス影響なしといった記述は、公式ドキュメントに書かれている仕様です。今回のPDIで実測して裏付けたものではありません。実機で確認したのは、あくまでリストとして開けたこと、Table APIで取得できたこと、Data Visualizationの検索候補に出たことまでです。
そのほかに確認していない項目は次のとおりです。本番環境やカスタム構成では挙動が異なる可能性があります。
Database Viewを新規に作成する手順
left_joinを有効にした場合の挙動
__ENC__で符号化されたsys_idの内部フォーマット
既定の一覧列がどのロジックで選ばれるか
Data Visualizationで実際にグラフを保存するところまでの動作
スコープアプリ内で作成した場合の扱い
本番規模のデータでのパフォーマンス実測