エス技研

WordPress、CakePHP、PHP、baserCMSなどの Web系システムを中心に情報を提供します!


CakePHP3のInsert On Duplicate Key Update(upsert)構文を解説・バルク処理も

   

CakePHP3でInsert On Duplicate Key Update(upsert)を処理

 
CakePHP3はフレームワークですので、データベースへのアクセスが簡単にできるようになっています。
 
ですが、「Insert … On Duplicate Key Update構文」については、Cookbookを探してもわかりにくかったので、改めてその解説をしようと思います。
 
 

Insert … On Duplicate Key Update構文とは

 
「Insert … On Duplicate Key Update構文」は、Updateと Insertをつなげて「Upsert」とも呼ばれている機能で、保存するレコードがすでにあれば Updateし、なければ Insertするという便利な機能です。
詳しくは下記の記事などが参考になります。
Insert On Duplicate Key Update構文の使い方
 
MySQLオフィシャル
https://dev.mysql.com/doc/refman/5.6/ja/insert-on-duplicate.html
 
 

CakePHP3の標準の更新(Update)処理について

 

サンプルとなる Topicsテーブル

 
今回は、下記の Topicsテーブルを想定します。
普通は想定しませんが、同一日に同一カテゴリーの topics(お知らせ)は配信しないということで、「category_id」「topics_date」の 2つで「topics_unique」というユニークキーを設定しています。
このキーと重複するレコードは Updateし、重複しない場合は Insertするという処理です。
※「Insert … On Duplicate Key Update構文」を利用する場合は、ユニークキーの設定が必要です。
 

 
 

CakePHP3で Bakeしたときの処理内容

 
CakePHP3で Bakeすると、アクション「edit」は下記のようになります。
これは、「id」をキーとしてレコードを取得し、入力された値で Updateするという処理です。
 

 
 

CakePHP3で「Insert … On Duplicate Key Update構文」を処理する場合

 
これを、入力された「category_id」「topics_date」が一致した場合に Updateする場合は以下のようになります。
 

 
 

「Insert … On Duplicate Key Update構文」を foreach()で処理する

 
$this->Topics->find()->where()->first()」の処理で「category_id」「topics_date」が一致するレコード取得を試みて、レコードが取得できたか出来なかったかで処理を分けています。
 
上記のような処理を書くことはほとんどないと思いますが、csvファイルなどを取り込む処理などで複数レコードがある場合は、上記を参考に取得したレコードを foreach()でぐるぐる回す処理にすれば OKです。
 

 
 

「Insert … On Duplicate Key Update構文」をバルク処理する方法

 
上記の方法でも処理は可能なのですが、1レコードごとに Selectしてレコードの有無を確認して、その上で Updateか Insertをしますのでレコード数が多いときは処理時間が問題になってきます。
 
そんなときのためにバルク処理も用意されています。
(「バルク処理」は、1レコードずつの処理ではなく、大量のデータをまとめて処理する方式です。)
 
 

 
 
ポイントとしては「epilog()」の部分ですね。
ここに記述するのは、ユニークキーになる項目ではなく、更新する項目を記述する項目という点です。
 
今回は、「$query->insert($columns);」の処理で「$columns」で配列全体を指定しましたが、「$query->insert(["title","body"]);」のように、登録するカラム名を直接記述する方法でも問題ありません。
 
 

「modified」を更新したい場合は更新項目に追加する

 
前項の処理を実行した場合、「modified」は更新されません。
 
先に紹介した「foreach()」の処理では CakePHP3で処理するため、レコード更新時には自動的に「modified」も更新されます。
ですが、バルク処理をした場合は前項の記述内容では「modified」は更新されないため、「modified」も更新したい場合はその内容も記述する必要があります。
 
記述する内容は、「epilog()」の行のみですが、下記の通り「, modified=now()」を追記します。
 

 
 

CakePHP 3.4以降では記述方法が変更に

 
また、CakePHP 3.4以降は下記のように推奨の記述方法が変更されています。
 

 
 

Insert … On Duplicate Key Update構文に関連する記事

 
CakePHP2の頃の話や、ここで紹介した「Insert … On Duplicate Key Update構文」の方法が分からずに直接 SQLを実行する方法で紹介した記事などを以下に書いています。
 
Insert On Duplicate Key Update構文の使い方
CakePHP 2.3でOn Duplicate Key構文を実装
CakePHP3で生の SQLの実行はConnectionManagerを使う
 
 

CakePHP3の関連記事

CakePHP3でレコードを保存(追加、更新、Insert、Update)する複数の方法を紹介
CakePHP3でモデルなしフォームからCSVをアップロードしレコードを更新する方法解説
CakePHP3でPHP Simple HTML DOM Parserを使ってスクレイピングする方法
CakePHP3のInsert On Duplicate Key Update(upsert)構文を解説・バルク処理も
CakePHP3の1対多での連携を中間テーブルを使った多対多の連携に変更するときの手順
CakePHP3でデフォルトのソート条件を設定してユーザの選択肢たソート条件を有効にする方法
CakePHP3で Ajaxを使う方法の解説。3.6以降対応。Successとthenの両方を解説。
CakePHP3でパンくずの指定は HTMLヘルパーを使って指定する方法を解説
CakePHP3にOGPをfetch、asignを利用してテンプレートごとに指定する方法を解説
CakePHP3のOGPはHTMLヘルパーの$this->Html->meta()を使って設定
 
その他の「CakePHP3」に関する記事一覧
 
 

 - CakePHP 2.x 3.x

GoogleAdwords

GoogleAdwords

最後までお読みいただきましてありがとうございます。
この記事が参考になったと思いましたらソーシャルメディアで共有していただけると嬉しいです!

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

下記の空欄を埋めてください。 * Time limit is exhausted. Please reload CAPTCHA.

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

※入力いただいたコメントは管理者の承認後に掲載されます。

  関連記事

CakePHP3のCakeDC/Usersの画面、メール本文テンプレートのカスタマイズ方法解説
CakePHP3のCakeDC/Usersの画面、メール本文テンプレートのカスタマイズ方法解説

CakeDC謹製Usersプラグインの紹介。ユーザ新規登録の流れを紹介しつつテンプレートファイルがどこにあるか、設定情報ファイルがどこにあるか、を説明しつつカスタマイズの方法を解説します。

VirtualBoxにCakePHP3を設置。必要なCentOS、Apache、PHP、MySQL、Composerをインストールし設定する。
VirtualBoxにCakePHP3を設置。必要なCentOS、Apache、PHP、MySQL、Composerをインストールし設定する

VirtualBoxにCentOS、Apache、MySQL、PHPをインストールするところから初めてCakePHP3の開発環境を構築する手順を詳細解説。この記事1つで全ての設定が完了する。

CakePHP 2.3 連携先のテーブルの項目で条件抽出する場合

アソシエーション(連携)している先のテーブルの項目で条件抽出する際の考え方と注意点をサンプルソースを用いて説明しています。

CakePHP3でレコードを追加、更新(Insert、Update)する複数の方法を紹介
CakePHP3でレコードを保存(追加、更新、Insert、Update)する複数の方法を紹介

CakePHP3でレコードを追加、更新(Insert、Update)する記述方法を解説。1件ずつ処理、全件をまとめて処理、条件に該当する複数件のレコードを処理方法をサンプルコードを用いて解説。

CakePHP3で現在処理しているコントローラー名、アクション名を取得する方法
CakePHP3で現在処理しているコントローラー名、アクション名を取得する方法

CakePHP3で現在処理しているコントローラー名、アクション名を取得する方法を解説。複数の方法があるが、getParam()メソッドを使う方法が汎用性があって便利かも。

CakePHP3のバージョンを指定してインストールする詳細な手順を解説
CakePHP3のバージョンを指定してインストールする詳細な手順を解説

CakePHP3のバージョンを指定してインストールする方法を詳細解説。CakePHP3のインストールはComposerを使うため設定もほぼ自動で完了。データベースの接続情報を記載すればアプリ開発のベースが整う。

CakePHP3にOGPをfetch、asignを利用してテンプレートごとに指定する方法を解説
CakePHP3にOGPをfetch、asignを利用してテンプレートごとに指定する方法を解説

CakePHP3でOGPを設定する方法を解説。fetch、assignを使用しレイアウトファイルに編集した変数にテンプレートファイルから値を指定する。これを利用してOGPを編集する。

CakePHP3のアソシエーション機能を使い関連レコードをまとめて削除

CakePHP3でレコードを削除する際に関連するレコードをまとめて削除する機能の解説。フレームワークのメリットを存分に発揮し、コマンドを1行追加するだけで実装可能。

CakePHP3で /Layout/defult.ctpにある titleタグ、h1タグを編集する方法
CakePHP3で /Layout/defult.ctpにある titleタグ、h1タグを編集する方法

CakePHP3でtitleタグ、h1タグのテキストをデフォルトから変更する方法を解説。テンプレートファイルに「$this->assign()」でテキストを指定して「/Layout/defult.ctp」で受け取る。

CakePHP3のビューで受取ったテーブルのオブジェクトを連想配列に変換する方法
CakePHP3のビューで受取ったテーブルのオブジェクトを連想配列に変換する方法

コントローラーからビューに送ったテーブルのオブジェクトを連想配列に変換し、ビューの中で自由に使えるようにするメソッド「toArray()」の解説。連想配列に変換できれば利用度アップ!