Webサイト制作コースのお申し込みはこちら Webサイト制作コースのお申し込みはこちら

データベースで複数のケースを一度に済ませたい場合があります。

例えばデータベースの任意のテーブルにデータが存在していない場合には新規追加、データが存在していた場合には更新に切り替えるといったようなケースです。

これを実現させるには「merge」というSQL文を使用すれば解決できます。

そこで今回はこのmerge文について解説してみたいと思います。

このmarge文を使えるようになれば、データベース操作が一段と楽になりますので、しっかりと学習しましょう。

mergeとは

margeは、任意のテーブルに対象レコードが存在している場合にはUPDATE(更新)をし、存在していない場合にはINSERT(挿入)をするといった処理に使われる文です。

すぐに想像できるものとしては会員情報ではないでしょうか。

会員情報システムでは、会員Noや住所及び電話番号などを基点として、該当するレコードがあれば更新、なければ新規登録します。

この処理を完結にさせるために思いつく一連の流れは

「SELECT文を実行してレコードを取得」

「IF文でデータの有無を判断する」

「もし該当するレコードが存在すればUPDATEを実行」

「該当するレコードが存在しなければINSERTを実行」

というような形でしょう。

このようにケースによって処理を切り替えることは、データベースを使ったアプリケーション開発ではよく使われる手段です。

しかしSQLの特性上、SELECT処理とUPDATE及びINSERT処理を一つのクエリで実行することは不可能なため、こういった場合にmergeを使います。

margeステートメントと記述方法

先ほども説明したように、mergeは[ INSERT、UPDATE、DELETE ]の対象となるテーブルとデータを比較して、該当レコードが存在する場合としない場合で分岐処理を行います。

この章ではこれらのステートメントに必要な構成要素について解説していきます。

MARGE [ INTO ]

INSERT, UPDATE, DELETE操作を行う対象のテーブルを指定します。

記述方法は次の通りです。

  1. [操作対象のテーブル] AS [代替名]

USING

INSERT, UPDATE, DELETE操作を行う対象のテーブルと比較するデータを指定します。

この時、比較対象となるデータにはSELECTを使用します。

記述方法は次の通りです。

  1. [比較対象となるデータ] AS [代替名]

ON

操作対象テーブルと比較対象となるデータの比較条件を指定します。

WHEN MATCHED THEN

UPDATEを記述する要素で、捜査対象テーブルにレコードが存在する場合の処理を指定します。

WHEN NOT MATCHED THEN

INSERTを記述する要素で、対象テーブルにレコードが存在しない場合の処理を指定します。

WHEN NOT MATCHED BY SOURCE THEN

DELETEを記述する要素で、比較対象となるデータにレコードが存在しない場合の処理を指定します。

margeの使い方

一通りmargeの説明が終わりましたのでここからは実際にどのように使うかについて解説していきます。

まずはサンプルテーブルの説明です。

  1. // 社員テーブル
  2. MariaDB [sample]> SELECT * FROM employee;
  3. +----+----------+-----+--------+
  4. | id | name | age | status |
  5. +----+----------+-----+--------+
  6. | 1 | Arex | 30 | R |
  7. | 2 | Jackson | 23 | NR |
  8. | 3 | Jonathan | 21 | NR |
  9. | 4 | Noah | 25 | R |
  10. | 5 | Aiden | 50 | R |
  11. | 6 | Caden | 29 | NR |
  12. | 7 | Smith | 36 | R |
  13. | 8 | Palmer | 42 | R |
  14. | 9 | Thomas | 50 | R |
  15. | 10 | Walker | 33 | R |
  16. +----+----------+-----+--------+
  17. 10 rows in set (0.000 sec)
  18.  
  19. // 退職者テーブル
  20. MariaDB [sample]> SELECT * FROM retiree;
  21. +----+------+--------+-----+--------+
  22. | id | code | name | age | status |
  23. +----+------+--------+-----+--------+
  24. | 1 | 5 | Aiden | 40 | R |
  25. | 2 | 9 | Thomas | 50 | R |
  26. +----+------+--------+-----+--------+
  27. 2 rows in set (0.000 sec)

二つのテーブルはそれぞれ社員と退職者のテーブルです。

退職者テーブルの”code”は社員テーブルの”id”を参照しています。

UPDATEが実行されるケース

以下は「退職者テーブルにデータが存在した場合、年齢を書き換える」といったケースのサンプルコードです。

  1. MERGE INTO retiree AS RT
  2. USING
  3. (SELECT
  4. 5 AS id,
  5. 'Aiden' AS name,
  6. 50 AS age,
  7. 'R' AS status
  8. ) AS ET
  9. ON
  10. (
  11. RT.id = ET.id
  12. )
  13. WHEN MATCHED THEN
  14. UPDATE
  15. SET
  16. id = ET.id,
  17. name = ET.name,
  18. age = ET.age,
  19. status = ET.status
  20. WHEN NOT MATCHED THEN
  21. INSERT (id, name, age, status)
  22. VALUES
  23. (
  24. ET.id,
  25. ET.name,
  26. ET.age,
  27. ET.status
  28. )
  29. ;
  30.  
  31.  
  32. id name age status
  33. ---- --------- -------- -------------
  34. 5 Aiden 50 R
  35. 9 Thomas 50 R

実行の結果、retireeテーブルには既にid=5のレコードが存在したため、対象テーブルであるretireeテーブルの該当レコードがが更新されていることが確認できます。

INSERTが実行されるケース

では次に「退職者テーブルにデータが存在しない為、新規追加される」といったケースのサンプルコードを見てみましょう。

  1. MERGE INTO retiree AS RT
  2. USING
  3. (SELECT
  4. 3 AS id,
  5. 'Jonathan' AS name,
  6. 21 AS age,
  7. 'NR' AS status
  8. ) AS ET
  9. ON
  10. (
  11. RT.id = ET.id
  12. )
  13. WHEN MATCHED THEN
  14. UPDATE
  15. SET
  16. id = ET.id,
  17. name = ET.name,
  18. age = ET.age,
  19. status = ET.status
  20. WHEN NOT MATCHED THEN
  21. INSERT (id, name, age, status)
  22. VALUES
  23. (
  24. ET.id,
  25. ET.name,
  26. ET.age,
  27. ET.status
  28. )
  29. ;
  30.  
  31. id name age status
  32. ---- --------- -------- -------------
  33. 5 Aiden 50 R
  34. 9 Thomas 50 R
  35. 3 Jonathan 21 NR

実行の結果、retireeテーブルには対象テーブル(employee)のid=3に該当するレコードが存在しなかったため、操作対象テーブルであるretireeにデータが新規追加されていることが確認できます。

UPDATEとINSERTが1回のクエリで実行されるケース

UPDATEとINSERTを一つのクエリで同時処理させるためには、USING内で指定するSELECTの条件にWHEREを使うなどの方法があります。

  1. UPDATE
  2. employee
  3. SET
  4. age = 45
  5. WHERE
  6. id = 5
  7. ;
  8.  
  9. MERGE INTO retiree AS RT
  10. USING
  11. (SELECT
  12. id,
  13. name,
  14. age,
  15. status
  16. FROM
  17. employee
  18. WHERE
  19. age >= 40
  20. ) AS ET
  21. ON
  22. (
  23. RT.id = ET.id
  24. )
  25. WHEN MATCHED THEN
  26. UPDATE SET
  27. RT.age = ET.age
  28. WHEN NOT MATCHED THEN
  29. INSERT
  30. (
  31. id,
  32. name,
  33. age,
  34. status
  35. )
  36. VALUES
  37. (
  38. ET.id,
  39. ET.name,
  40. ET.age,
  41. ET.status
  42. )
  43. ;
  44.  
  45. id name age status
  46. ---- --------- -------- -------------
  47. 5 Aiden 45 R
  48. 9 Thomas 50 R
  49. 8 Palmer 42 R

サンプル用にまず「id=5」に該当するレコードの年齢を45歳に書き換えた上で、mergeではUSINGで参照させるデータを選別して「age>=40」のレコードだけを対象としています。

こうすることで、元々retireeテーブルに存在していた2つのレコードは更新、更にretireeテーブルに存在しなかったレコードは追加という処理が同時に実行されています。

まとめ

いかがでしたか?今回はmerge文について解説してみました。

記述を省略できることはミスを減らすことにも直結します。

またSQLを使いこなせるようになればデータベースの設計もより上達しますので、こういった方法を数多く覚えていくことを心がけましょう。

エンジニアになりたい人に選ばれるプログラミングスクール「ポテパンキャンプ 」

ポテパンキャンプは卒業生の多くがWebエンジニアとして活躍している実践型プログラミングスクールです。 1000名以上が受講しており、その多くが上場企業、ベンチャー企業のWebエンジニアとして活躍しています。

基礎的な学習だけで満足せず、実際にプログラミングを覚えて実践で使えるレベルまで学習したいという方に人気です。 プログラミングを学習し実践で使うには様々な要素が必要です。

それがマルっと詰まっているポテパンキャンプでプログラミングを学習してみませんか?

卒業生の多くがWebエンジニアとして活躍

卒業生の多くがWeb企業で活躍しております。
実践的なカリキュラムをこなしているからこそ現場でも戦力となっております。
活躍する卒業生のインタビューもございますので是非御覧ください。

経験豊富なエンジニア陣が直接指導

実践的なカリキュラムと経験豊富なエンジニアが直接指導にあたります。
有名企業のエンジニアも多数在籍し品質高いWebアプリケーションを作れるようサポートします。

満足度高くコスパの高いプログラミングスクール「ポテパンキャンプ」

運営する株式会社ポテパンは10,000人以上のエンジニアのキャリアサポートを行ってきております。
そのノウハウを活かして実践的なカリキュラムを随時アップデートしております。

代表の宮崎もプログラミングを覚えサイトを作りポテパンを創業しました。
本気でプログラミングを身につけたいという方にコスパ良く受講していただきたいと思っておりますので、気になる方はぜひスクール詳細をのぞいてくださいませ。