Welcome to Community Week 2025! Join us to learn, connect, and be recognized as we celebrate the spirit of Community and the power of AI. Get the details  

大量データをCSVファイルでエクスポートする方法

Yuki21
Tera Expert

お世話になっております。
テーブルに格納されているレコードを全件CSVファイルでエクスポートするための手段について質問させてください。

①リスト表示後、「列のオプション」を右クリックし、エクスポート>CSVを選択
②https://<インスタンス名>.service-now.com/<テーブル名>_list.do?CSV

上記2つ以外の方法はありますでしょうか?
上記の方法ですと処理時間がタイムアウトしないようなレコード数のデータのみエクスポート可能な認識です。
タイムアウトするような大量レコードのエクスポートはServiceNowが推奨していないことは認識しておりますが、
テーブルデータバックアップの要件として挙がっており、対策をご存知であればご教示いただければと思います。

1 ACCEPTED SOLUTION

iwai
Giga Sage

バックアップ目的であれば、CSVファイルよりXMLファイルで保存するべきです。
復元するときXMLファイルインポートなら完全に元のレコードに戻ります。
復元するときに取り込める最大数の制限を受けるので、巨大なファイルを復元できません。
そのため、大量データのExport方法は、1万件程度に分割してDownloadします。

補足、バックアップであればReferenceしているテーブル(ユーザー関連など)もすべてバックアップをしておきましょう。(Reference先のSYSIDを正しく参照できるようにXMLファイルで関連テーブルすべてをバックアップする)

単純に今回だけデータを手動でバックアップしたい要件であれば、下記のようなScriptで分割ダウンロードのURLを作成できます。Script Backgroundで実行してみてください。インスタンス名など各種パラメーターは環境に合わせて変更してください。

var myInstance = 'myInstance'; // インスタンス名
var myTable = 'incident'; // エクスポートテーブル名
var myQuery = ''; // エクスポートQuery 必要な場合に記載
var myFileType = 'CSV'; // エクスポート形式 CSV,XLSX,UNL(UNL=XML形式でダウンロード)
var setLimit = 10000; // エクスポート分割行数
var sysid = '';
var exportUrl = [];
var gr = new GlideRecord(myTable);
gr.initialize();
var fields = gr.getFields();
var myField = [];
var num;

exportUrl.push('https://' + myInstance + '.service-now.com/' + myTable + '_list.do' +
    '?sysparm_query=' +
    (!!myQuery ? encodeURIComponent(myQuery) + '%5EORDERBYsys_id' : 'ORDERBYsys_id') +
    '&sysparm_record_count=' + setLimit +
    '&sysparm_default_export_fields=all&' + myFileType);
num = setLimit - 1;
do {
    gr = new GlideRecord(myTable);
    gr.initialize();
    if(myQuery) gr.addEncodedQuery(myQuery);
    gr.orderBy('sys_id');
    gr.chooseWindow(num, num + 2);
    gr.query();
    if (gr.next()) {
        sysid = '' + gr.getValue('sys_id');
        exportUrl.push('https://' + myInstance + '.service-now.com/' + myTable + '_list.do' +
            '?sysparm_query=sys_id%3E' + sysid +
            (!!myQuery ? '%5E' + encodeURIComponent(myQuery) : '') +
            '%5EORDERBYsys_id' +
            '&sysparm_record_count=' + setLimit +
            '&sysparm_default_export_fields=all&' + myFileType);
    }
    num += setLimit;
} while (gr.next());
for (num = 0; num < exportUrl.length; num++) {
    gs.info(exportUrl[num]);
}

 

定期的に自動バックアップをしたいなら、バックアップするサーバー側にPowershellやPythonなどで、定期的に分割ダウンロードするScriptを組むと良いです。もし要望があれば投稿します。

View solution in original post

11 REPLIES 11

iwai様

ご返信ありがとうございます。
スクリプトのご連携につきましてもありがとうございます。

大量データの場合、分割してダウンロードする方法が推奨されていることも理解いたしました。
数億件のレコードを退避することを想定していたのですが、方針そのものを見直す方向で検討したいと思います。

参考までにお聞きしたいのですが、URIの中のORDERBYはsys_idのみ指定可能でしょうか?
別の項目(日付)を指定するようにしたらレスポンスなしになりました。

  • 質問『URIの中のORDERBYはsys_idのみ指定可能』
  • 回答、今回の分割ダウンロードの仕組みとしてはsys_idのみ指定可能です、指定しても順序は変わらないです。Queryの機能としては複数指定可能です。
    例:incident_list.do?sysparm_query=active%3Dtrue%5EORDERBYpriority%5EORDERBYopened_at%5EORDERBYcaller_id
    incident_list.do?sysparm_query=active=true^ORDERBYpriority^ORDERBYopened_at^ORDERBYcaller_id

分割ダウンロードの仕組みとしては、sys_id(重複の無い値)でソートすることで分割しています。重複する値では正確な数量で分割できません。重複しない値でソートした後では、他のソートを付け足しても、順序が変わる余地はありません。

例:3つごとに分割する例。sys_idは重複しないので、他のソートを付け足しても順序は変わらない。

Linesys_idCount
1a1
2b2
3c3、ここで分割
4d1、sys_id>cのQuery条件でデータ取得するのでここから始まる
5e2
6f3、ここで分割

数億件のレコードの退避に耐えられるか検証したことがないので、実際に1000万件ぐらいの分割数でダウンロード可能かどうか、確かめてみてください。XMLの最大数(下の図の設定)も1000万件やそれ以上に設定して正しくダウンロードできるか確かめてみてください。

find_real_file.png

(追記、XML最大数のプロパティーには”com.glide.processors.XMLProcessor.max_record_count”と言うものもあるようなので、設定してみてください。Export Limits: Beyond the 50K - Support and Troubleshooting (servicenow.com) )

XMLダウンロードの場合、URLのパラメーターを”UNL”にすると即時ダウンロードできます。参考例のScriptにも記載しておきました。(例myFileType = 'UNL')ブラウザで”XML”を指定した場合は、最初にブラウザ画面にXMLが表示されてダウンロードが始まらないです。”UNL”にすると即時ダウンロードできます。

iwai様

ご回答ありがとうございます。

大変参考になりました。

kaka_1234
Tera Contributor

こちら、サーバー側に書くスクリプトはどのようなものになるか、だけでもよいのでご教授いただけないでしょうか?

晃敏池
Tera Contributor

te