Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
Sawa_Ito
Product and Topic Expert
Product and Topic Expert


このページは、以下の英語ページの抄訳です。最新の情報については、英語ページを参照してください。

 

 

 

この記事のオリジナルは、Glenn Paulley が sybase.com に 2009 年 4 月に掲載したものです。その中で、Glenn は SQL Anywhere における MERGE 文について解説しています。MERGE 文に関する最新の情報はこちらを参照ください。

 

 

 

 

MERGE 文は、SQL:2003 ANSI/ISO の F312 の機能として登場しました。MERGE は、行のセットを挿入する必要があり、かつ、クリーニングまたは他の ETL (Extract-Transform-Load) プロセスが必要な時に便利です。MERGE を使用すると、1 つの文で新規データ挿入と既存の行の更新をセットで対応できる洗練されたロジックを実装することができます。

このブログ記事では、MERGE 文の機能について簡単に概要を説明するとともに、SQL:2003 と SQL:2008 間でどのような変更があったのか、さらに SQL Anywhere でサポートされている拡張機能について説明します。

ここでは、私の同僚である Anil Goel が 2008 年 8月にラスベガスで開催された Sybase Techwave においてプレゼンした MERGE 文とマテリアライズドビューに関する資料を借りて説明したいと思います。

 


 

テーブルに行を挿入する処理を行う場合、「INSERT-else-UPDATE」処理を実行する必要がある場合があります。これこそが、MERGE 文を使用する理由です。さらには以下のようなメリットがあります。

 

INSERT の代替アクションを設定することができます。例えば


• 特定の行において条件次第で INSERT をスキップ、または UPDATE を行う


• 既存の行を DELETE する


などのように任意の条件を設定し、代替アクションを行わせることができます。


 

空ではないテーブルTがあり、以下のように入力行データ S を処理するとします。

 





  1. FOR each input row in S DO

  2.   IF EXISTING THEN // もし、行Sと同一の主キーの行が既にテーブルTに存在する場合

  3.     IF condition-1 THEN SKIP // 条件 1 にマッチした場合は処理をスキップ

  4.     ELSE IF condition-2 THEN ERROR //条件 2 にマッチした場合はエラーを返す

  5.     ELSE IF condition-3 THEN DELETE FROM T //条件 3 にマッチした場合はその行をテーブル T から削除

  6.     ELSE UPDATE T //条件 1 ~ 3 にマッチしなかったらその行を更新する

  7.   ELSE // 行 S と同一の行がテーブル T に存在しなかった場合

  8.     IF condition-4 THEN SKIP //条件 4 にマッチした場合は処理をスキップ

  9.     ELSE IF condition-5 THEN ERROR //条件 5 にマッチした場合はエラーを返す

  10.     ELSE INSERT INTO T //条件 4 ~ 5 にマッチしなかったら行 S を挿入する

  11. END




 

このロジック全体を、以下のような 1 つの MERGE 文として実行することが可能です。以下の例では、テーブル T にクライアントマシン上のテキストファイルを読み込み、それに含まれる行をマージしています。これは、version 11 の OPENSTRING 句を使用することでテーブルのように扱うことができます。

 





  1. MERGE INTO T

  2. USING (SELECT * FROM OPENSTRING( FILE '/usr/paulley/techwave/2008/data1.txt')

  3.           WITH( id INT, qty INT, cmt LONG VARCHAR)  S) S //CSVファイルを読み込み、区切り文字毎にid,qty,cmtという変数で以下扱えるようにします。行全体はSという変数となりますので各カラムにはS.カラム名、例えばidカラムならS.idという形でアクセスする事ができます。

  4. ON PRIMARY KEY

  5. WHEN NOT MATCHED AND S.cmt = 'ignore' THEN SKIP //主キーの重複が発生せず、テキストファイル上の行のcmtカラムに相当するデータがignoreではなかった場合はこの行をスキップ

  6. WHEN NOT MATCHED AND S.qty < 0  THEN RAISERROR //主キーの重複が発生せず、テキストファイル上の行のqtyカラムに相当するデータが0以下ではなかった場合はエラーを返す

  7. WHEN NOT MATCHED AND S.qty = 0 THEN INSERT VALUES( S.id, 1 ) //主キーの重複が発生せず、テキストファイル上の行のqtyカラムに相当するデータが0の場合はテーブルTに( S.id, 1 ) を挿入する

  8. WHEN NOT MATCHED THEN INSERT VALUES( S.id, S.qty ) //主キーの重複が発生せず、上記の3条件に合致しなかった場合はテーブルTに( S.id, S.qty )を挿入する


  9. WHEN MATCHED AND S.cmt = 'ignore' THEN SKIP

  10. WHEN MATCHED AND S.cmt = 'new'  THEN RAISERROR //主キーの重複が発生し、テキストファイル上の行のcmtカラムに相当する場所のデータがignoreの場合はこの行をスキップ

  11. WHEN MATCHED AND T.qty + S.qty

  12. ...




 

 

MERGE 文 - 概要


 

SQL:2003 で定義されている MERGE 文は、最大でも WHEN MATCHED 1つと WHEN NOT MATCHED 句1つしか許していません。

 

SQL:2003 MERGE 文は、以下のとおりです。

 

• target-object の各行で、ソースとターゲットから 'matching' # 行を見つけるために、MERGE サーチ条件が source-object の各行を TRUE と評価するかどうか決める


• マッチする行が発見された場合には、エラーを生成する。


• 見つかった場合には、マッチング行 1 行を行のセットに追加し、存在する場合 WHEN MATCHED 句で処理する。


• 存在する場合、WHEN NOT MATCHED 句が target-object 行にマッチできない source-object の行を処理する。


 

SQL:2008 の Feature F313 では、複数の WHEN [NOT] MATCHED 句をオプショナルのサーチ条件で許可しています。この場合、WHEN 句の順番が問題になります。実行されるサーチ条件を満足させるのは、最初の WHEN 句のマージアクションです。しかしながら、Feature F313 でも、標準の MERGE 文はそれほどフレキシブルではありません。WHEN MATCHED 句が実行できる唯一のオペレーションは、UPDATE であり、WHEN NOT MATCHED 句が実行できる唯一のオペレーションは INSERT です。SQL Anywhere 11 では、MERGE 文の機能をいくつかの方法で拡張しています。それらのいくつかは、2002年の SQL Anywhere version 8 で実装された、それまでの INSERT ... ON EXISTING 文を引き継いでいます。

 

OPENSTRING 構造 を使用して、クライアントマシン上のテキストファイルのデータを MERGE に使用できるように拡張しています。


• 明示的なカラムリストを使用して入力行データのカラムとMARGE 先のテーブルカラムのマッチングを変更できるように拡張しています。


WITH AUTO NAME 構文を使用してカラム順ではなくカラム名によるカラムのマッチングができるように拡張しています。


MERGE サーチ条件は、プライマリーキー重複に基づく場合、省略形として ON PRIMARY KEY が使用可能です。


•  WHEN MATCHED で実行できるアクションが拡張されています。


• 既存の行を DELETE


RAISERROR [ error-number ]


SKIP


• 既存の行を UPDATE [ DEFAULTS { ON | OFF }


WHEN NOT MATCHED で実行できるアクションが拡張されています。


• 入力行データを INSERT する


RAISERROR[ error-number ]


SKIP


 

ターゲットテーブルの INSERT、DELETE、UPDATE 、トリガーの構文と並び、MERGE 文の構文の詳細は、SQL Anywhere のマニュアルに記載されています。

SQL Anywhere 11 でサポートされている MERGE 文を BNF で記述すると以下のとおりです。

 





  1. merge                ::= "MERGE" "INTO" merge_into_tabterm merge_using

  2.                         simple_tabterm merge_on_clause merge_op_list

  3. merge_using          ::= "USING" | "USING WITH AUTO NAME"

  4. merge_into_tabterm  ::= ( tabref | "(" query_expr ")" as identifier

  5.                         | "(" "WITH" with_list query_expr ")" as identifier ) derived_collist

  6. merge_on_clause      ::= "ON" merge_search_cond

  7. merge_search_cond    ::= searchcond

  8.                         | "PRIMARY" "KEY"

  9.                         | "INDEX" indexname

  10. merge_op_list        ::= merge_op { "," merge_op }

  11. merge_op            ::= "WHEN MATCHED" "THEN" merge_matched_op

  12.                         | "WHEN MATCHED" "AND" searchcond "THEN"

  13.                           merge_matched_op

  14.                         | "WHEN NOT" "MATCHED" "THEN"

  15.                           merge_not_matched_op

  16.                         | "WHEN NOT" "MATCHED" "AND" searchcond

  17.                           "THEN" merge_not_matched_op

  18. merge_common_op      ::= "SKIP"

  19.                         | "RAISERROR"

  20.                         | "RAISERROR" integer_or_var

  21. merge_matched_op    ::= merge_common_op

  22.                         | "UPDATE SET" setlist

  23.                         | "UPDATE"

  24.                         | "UPDATE" "DEFAULTS" "ON"

  25.                         | "UPDATE" "DEFAULTS" "OFF"

  26.                         | "DELETE"

  27. merge_not_matched_op ::= merge_common_op

  28.                         | "INSERT" "VALUES" "(" ins_vallist ")"

  29.                         | "INSERT" "(" inscollist ")" "VALUES" "(" ins_vallist ")"

  30.                         | "INSERT"

  31. ins_vallist          ::= { ins_valitem "," } ins_valitem

  32. ins_valitem          ::= "DEFAULT" | expression

  33. inscollist          ::= { inscolname "," } inscolname

  34. inscolname          ::= identifier [ "." identifier ]




 

Techwave 2008 での我々のプレゼンに上記のコンテンツの大半を入れてくれた Anil Goel に感謝します。

 

 

===

 

SAP SQL Anywhere に関する詳細情報は、SAP SQL Anywhere Communityページ<英語> を参照してください。

 

上記のコミュニティーに掲載されている技術情報は、順次SQL Anywhere 日本語コミュニティ

に掲載しています。

 

SQL Anywhere に関してはまずはこちらをご参照ください。無期限でご利用いただける無償の Developers Edition もこちらからダウンロードが可能です。

 

SQL Anywhere に関して技術的な質問のある方はコミュニティに登録し、
「Ask a Question」機能をご利用ください。

Language には「Japanese」、
Primary Tag には「SAP SQL Anywhere」を選択
User Tagに「sql anywhere」「sql anywhere Japanese question」

を入力してください。

不具合につきましては、サポート契約者様専用の問い合わせ方法にてお問い合わせください。

 

======================
ご購入に関するお問い合わせ

こちらよりお問い合わせください。