「rex0220 kSQL アクションプラグイン」の実践編です。
書き込みの前の確認と上限、実行を許す人、押した人の権限で動くことの意味、ログアプリによる記録と二重実行の防止(ロック)、そして途中で止まったときの回復をまとめます。
シリーズ: 概要 / ① 詳細画面 / ② 一覧 / ③ 集計 / ④ 運用(この記事) / ⑤ 事例 / ⑥ イベント / ⑦ オーサリング / ⑧ 請求データ / ⑨ 締めの画面 / ⑩ どこに出すか / ⑪ 多言語 / ⑫ オーサリング改善
確認と安全
書き込みの確認
アクションごとに 2 つの方式を選べます。
| 方式 | 動き |
|---|---|
| 件数確認(既定) | 書き込みの前に確認を出します(下の文面) |
| 確認なし | 確認を出さずに書きます。書き込み上限の設定が必須です |
確認ダイアログは「書き込みの確認」という題で、次の形です。
書き込み先:集計 (4388)
内容:レコードを 1 件 更新します
テーブルの行を入れ替えます(足す 3 行 / 消える 3 行)
(この実行の合計 1 件・上限 50 件)
- 書き込む文が 2 つ以上あるアクションでは、先頭に「ステップ 1 / 3」が付きます。文番号ではなくステップで数えます(利用者は SQL を見ないので、文番号では対応づけられないため)。DECLARE のような書き込まない文は数に入れません
- 「更新」の語は、その文が実際に何をするかで「追加 / 更新 / 削除 / 並べ替え」に変わります(
UPSERTは中身に応じて「追加」か「更新」になります) - テーブル(サブテーブル)を書き換えるときは、2 行目に行数が出ます
- 書き込み上限は「起動 1 回で書いてよい合計件数」です。一覧の一括処理では、各レコードの実行ではなく選択した全体で 1 つの累計として数えます
- 数えるのはレコードの件数です。テーブル(サブテーブル)の行は別枠で、共通設定の「制限」の 「APPLY で変わる子行の上限」(既定 500)で抑えます。親 1 件+明細 10 行を書き換えるときは、書き込み上限には 1 件、子行の上限には 10 行として当たります
- 件数は書き込みの直前に確かめます。上限を超える文は書かずに、実行を中止します
- この処理はトランザクションではありません。途中で取り消したり失敗したりしても、前の文が書いた分は残ります(確認ダイアログにも表示します)。ASSERT や UPSERT で、同じ入力でもう一度実行しても結果が重ならない形に書くことをおすすめします
-
確認を待っている時間も、実行の制限時間(共通設定の「制限」のタイムアウト。既定 60 分)に入ります。確認を出したまま席を離れると、押したときにはもう時間切れで止まることがあります(ログの状態は
TIMEOUT) - 制限時間は書き込み上限とは数え方が違います。書き込み上限は一括全体の累計ですが、制限時間はレコード(グループ)ごとに計ります(切れたら残りは未処理にして止めます)。一括全体の時間を抑えたいときは、一括の最大件数か書き込み上限で抑えます
実行を許す人
アクションごとに、実行できる人(ユーザー・組織・グループ)を絞れます。誤操作の防止のための絞りで、データの防御は kintone のアクセス権で行ってください。
権限の運用
アクションは押した人の権限で動きます(API トークンは使いません)。SQL が自分のアプリだけを触るなら、ふだん使っている人はそのまま押せます。
実行するときに、必要な権限がユーザー・組織・グループのいずれかで付いていることが条件です(付け方は問いません)。足りないと kintone が断り、そのアクションは失敗します。
他のアプリに書くときは、次のようにします。
- アクションを実行する人のグループを作る
- SQL が触るアプリすべての権限をそのグループに付ける
| SQL | 要る権限 |
|---|---|
| 読む(SELECT・一時テーブル・ASSERT) | レコード閲覧 |
| INSERT | 追加 |
| UPDATE / REORDER | 編集 |
| DELETE | 削除 |
| UPSERT | 追加 + 編集 |
- ルックアップのある項目を更新するときは、参照先アプリのレコード閲覧も要ります(kintone の仕様)
- ログアプリを使うときは、ログアプリの閲覧・追加・編集もそのグループに付けます
- アクションの「実行を許す人」に同じグループを指定すると、設定と実際の権限がそろいます
kintone の権限はアプリに付くので、グループに入れた人はこのボタンを通さずに対象のアプリを直接開いて編集できます。「決まった SQL でだけ書かせる」ことはできないため、対象のアプリは集計・記録の専用にする、権限は必要な分だけにする、レコードのアクセス権で絞る、のいずれかで備えてください。
ログアプリ(任意)
プラグイン設定でログアプリを指定すると、実行のたびに記録を残し、別ユーザーとの二重実行を防ぎます。
-
ログアプリは kSQL Flow と同じ形式です(テンプレートから作れます)
-
実行の開始で RUNNING のレコードを作り、これがロックになります(ロックのキーはログアプリの重複禁止フィールドで、作成できた実行だけが進みます)。同じアクションを誰かが実行中のときは「ロック中」で止まります
-
排他の単位はアクションです(設定で「レコード別にロック」をオンにすると、詳細画面のボタンではレコード単位になります)。別のアクションや、プラグインの外からの更新による同一レコードの競合は防ぎません
-
イベント起動(保存後・ステータス変更)はロックを取りません。ログアプリに書けないときも実行します。イベントには押し直す人がいないので、止めると「やらなかったこと」が誰にも伝わらないまま、データだけが先に進むからです(関連レコード集計と同じ考え方)。記録はこれまでどおり残ります
-
ブラウザーが途中で閉じられるなどで実行が中断されると、RUNNING のレコードが残り、次の実行が「ロック中」で止まることがあります。解除は、その実行が本当に終わっている(動かしていた画面が閉じている)ことを確かめてから、ログアプリの該当レコードのステータスを変えて、ロックのキーを空にします。まだ動いている実行を解除すると、同じデータを 2 つの実行が同時に書くことになります
-
実行する人に、ログアプリのレコードの閲覧・追加・編集の権限が必要です
-
一覧の一括は、1 回で BATCH と JOB が 1 件ずつです(レコードごとには作りません)。内訳(対象・成功・失敗・条件外・未処理)は「詳細ログ」に入ります
-
「1 件ずつ」の一括で失敗したときは、どのレコードが失敗したかも「詳細ログ」の先頭に残ります(例「失敗したレコード: 301, 305, 312」。20 件まで、超えたら「ほか n 件」)
-
記録するのは状態・件数・所要時間・実行者などだけです。業務データの値・SQL の本文・パラメーターの値は書きません
-
ログアプリを指定しないときは、記録はレコードの更新者・変更履歴(kintone 標準)だけになり、別ユーザーの同時実行は防げません。複数の人が同じアクションを押す運用なら、ログアプリを指定することをおすすめします
イベントに置く SQL は「まるごと計算し直す」形に
ロックを取らないぶん、イベントに置く SQL は差分を足し引きせず、関係する範囲を毎回まるごと計算し直して反映する形にしてください。kintone の関連レコード集計が、1 レコードの変更で関係するレコード全体を集計し直すのと同じ考え方です。こう書けば、同じレコードを何度保存しても、ほかのレコードと前後しても、最新の正しい結果に落ち着きます。
| 書き方 | 何度動いても |
|---|---|
INSERT で足していく |
保存のたびに増えます(イベントには置かない) |
UPSERT |
同じ行を計算し直して上書きします |
全置換(DELETE → INSERT … SELECT) |
同じ結果になります |
REMOVE ALL ROWS + APPEND … SELECT
|
同じ行に戻ります |
親の値と明細のテーブルを両方直すときは、できれば 1 文にまとめてください。親の行があると分かっていれば、UPSERT と APPLY を分けずに書けます。
UPDATE 集計 SET 件数 = ..., 売上 = ... WHERE 顧客コード = @c
APPLY 明細 (REMOVE ALL ROWS; APPEND (担当者, 明細件数, 明細金額) SELECT ...);
1 文なら 1 レコードの書き込みになるので、別の実行と前後しても親と明細がずれません。2 文に分けると、親と明細が別々の時点のものになることがあります。
ボタンと一覧の一括は、これまでどおりロックを取ります。
イベントのログは「失敗だけ」が既定
イベントはそのレコードを保存するたびに起きます。すべて記録すると、1 日 100 件の更新で年に数万件になり、ほとんどが見る必要のないレコードです。
そこで、起動のダイアログの「イベント」の枠でアクションごとに選べるようにしています。
| 選択 | 記録 | ログアプリへの通信(成功時) |
|---|---|---|
| 記録する | 開始と終了(BATCH + JOB) | 4 回 |
| 失敗だけ記録する(既定) | 失敗・中止・上限・タイムアウトのときだけ、終了時に 1 回 | 0 回 |
| 記録しない | 残さない | 0 回 |
「失敗だけ」と「記録しない」では開始時の記録を作りません。イベントはロックを取らないので、先に作る必要が無いからです。保存のたびの通信が減るぶん、画面の戻りも軽くなります。
失うのは「始まって終わらなかった」痕跡だけです(その記録には件数も入っていません)。
ボタンと一覧の一括には効きません。 そちらは記録を作ることが二重実行を止める仕組みそのものなので、省けません。
途中で止まったときの回復
実行は押した人のブラウザーで動きます。タブを閉じた、PC がスリープした、回線が切れた、といった理由で途中で止まることがあります。そのときに何が残り、どう戻すかをまとめます。
何が残るか
| 残るもの | 中身 |
|---|---|
| ログアプリの RUNNING | JOB と BATCH の 2 件が RUNNING のまま残ります。JOB の job_key がロックなので、同じアクションの次の実行が止まります(ボタンと一覧の一括だけ。イベント起動は止まりません) |
| 書き込み | 止まった時点までの分は残ります(トランザクションではないため) |
| 画面 | 結果のダイアログは出ません |
件数(written_count など)は実行の終わりにまとめて書くので、中断した記録には入りません。どこまで書いたかは、書き込み先アプリの更新日時・更新者や、レコードの変更履歴で確かめてください。
気づき方
同じアクションを押すと、進行中の実行がダイアログに出ます。
経過の分はサーバーの時刻で数えるので、押した人の PC の時計がずれていても正しく出ます。[ログを開く]でその記録を新しいタブで開けます。
ほかの気づき方:
- 一覧パネルの「最近の実行」に、件数の代わりに経過の分と
RUNNINGが出ます。何時間も RUNNING のままなら、残ったロックを疑ってください - ログアプリの「実行中(ロック)」の一覧に並びます
その場で解除して実行する
ダイアログの[解除して実行]で、残ったロックを外してそのまま実行できます。
- 実行の制限時間を過ぎているとき(共通設定の「制限」のタイムアウト。既定 60 分)は「この実行はもう書き込みません」と出ます。制限時間を過ぎた実行はエンジンが打ち切っているので、安全に外せます
- 過ぎていないときは「まだ動いているかもしれません」と警告します。それでも押せます(通信が切れただけで何十分も待たされるのは困るので、自己責任で外せる形にしました)
- どちらでも「この実行を打ち切ってロックを外します(書き込みは途中までのまま残ります)」のチェックが要ります。チェックを入れるまで[解除して実行]は押せません
- 解除できるのはそのアクションを実行できる人です。ログの記録は実行する人の権限で書くので、ボタンを押せる人はもともとログアプリを編集できます(解除だけを別に許す設定はありません)。絞りたいときは、アクションの「実行を許す人」で押せる人を絞ってください
- 誰がいつ解除したかは、その記録の「詳細ログ」の先頭に「2026/11/01 21:32 rex0220 が解除しました」の 1 行として残ります
チェックを入れると[解除して実行]が押せるようになります。
解除された記録は、ABORTED・job_key は空・終了日時は解除した時刻、という形で残ります。書込件数が空なのは、件数を実行の終わりにまとめて書くためです。
解除のあとに元の実行が戻ってきても、書き込みの直前のロックの確認で止まります(下の「間違えて実行中のロックを外したら」と同じ動きです)。ロックを外しても勝手に実行はしないので、押す前に書き込み先を確かめてかまいません。
自動では外しません。プラグインは途中経過を記録しないので、本当に止まっているかはプラグインには分からないからです。判断は人がします。
手で直す
ボタンから直せないとき(そのアクションを設定から消した、実行環境名を変えた、など)は、ログアプリのレコードを直接直します。
| レコード | status | job_key | job_key_done |
|---|---|---|---|
| JOB | ABORTED |
空にする | 元の job_key(<実行環境名>:<アクションコード>) |
| BATCH | ABORTED |
空にする | 元の job_key(<実行環境名>:b:<バッチ実行 ID>) |
ロックは JOB の job_key(重複を禁止したフィールド)なので、ここを空にすれば次の実行が動きます。BATCH も同じように直しておくと、あとで一覧を見たときに分かりやすくなります。これは実行が正常に終わったときと同じ形です(終了時は job_key を空にして job_key_done へ写します)。
もう一度実行してよいか
-
UPSERT、DELETE→INSERT … SELECTの全置換、REMOVE ALL ROWS+APPEND … SELECTのように何度実行しても結果が同じな形で書いてあれば、そのまま実行してかまいません。足りない分が埋まり、重複もしません -
INSERTで足していくだけの SQL は、二重に入ることがあります。先に書き込み先を確かめてください
間違えて実行中のロックを外したら
実行中のアクションは、書き込みの直前に毎回ロックの持ち主を確かめます。外されていたら、そこで「中止しました(ログアプリのロックが解除されていました)」と出して、それ以上は書きません。すでに書いた分は残ります。
ログアプリに書けないとき
接続・権限・フィールドの不備でログアプリに書けないとき、ボタンと一覧の一括は「ログアプリに記録できないため実行しません」と出して実行しません。ロックを取れないまま走って二重に書く、ということは起きません。
イベント起動だけは実行します(記録は残りません)。ロックを取らない以上、記録できないことを理由に仕事を止める意味がないからです。
ネットワークが切れたとき
- SQL の実行中に通信が切れると、その文でエラーになります。記録まで書ければ
FAILEDで残ります - ログの作成(POST)の応答が届かなかったときは送り直さず、同じ実行の記録があるかを照会します。ロックが 2 つできることはありません
- ブラウザーごと落ちた場合は、上の「その場で解除して実行する」になります
関連記事
- rex0220 kSQL アクションプラグイン
- ① 詳細画面編(ボタンとイベント)
- ② 一覧編(選択したレコードをまとめて処理する)
- ③ 集計編(顧客別集計とテーブルへの書き戻し)
- ④ 運用編(ログアプリ・二重実行の防止・権限)(この記事)
- ⑤ 事例編(10 万件を集計して Dashboard Pro で見る)
- ⑥ イベント編(保存・ステータス変更・削除で自動実行する)
- ⑦ オーサリング編(設定を AI に作ってもらう)
- ⑧ 請求データ編(全体再計算で整合性を保つ)
- ⑨ 締めの画面編(押し忘れに気づくダッシュボード)
- ⑩ 画面のどこに出すか(ボタン・メニュー・パネルの使い分け)
- ⑪ 日本語・英語・中国語で使う(共通の文と多言語)
- ⑫ オーサリング改善編(AI に使わせて見つけた穴)
- 事例集(やりたいことから探す)




