SAP SQL Anywhere における SELECT 文内での UPDATE 文の使用 (過去のブログ記事より)
このページは、以下の英語ページの抄訳です。最新の情報については、英語ページを参照してください。
この記事のオリジナルは、Glenn Paulley が sybase.com に 2009 年 5 月に掲載したものです。その中で、Glenn は SQL Anywhere version 12 で追加された機能である 様々な DML クエリーにおける SELECT文 の使用について解説しています。
これは非常に便利で、軽く使える機能なため、繰り返し使用する価値があります。
例えば、insert 文の一部として新たに挿入された行のプライマリーキーを簡単に返すことができます。
例:
- SELECT pkey_col FROM (INSERT INTO mytable(col2) VALUES( ‘hello’)) REFERENCING (FINAL as t_final) order by 1
2009 年 5 月のブログ記事で、クエリーの FROM 句
内のテーブル表現として update DML 文を使用できる IBM DB2 製品の SQL 言語機能について賞賛しましたが、DB2 の構文を以下の簡単な例で説明します。
- SELECT T_updated.*
- FROM NEW TABLE ( UPDATE T SET x=7 WHERE y=6 ) AS T_updated
- WHERE T_updated.pk IN ( SELECT S.fk FROM S WHERE S.z = 8 )
この構造は、修正した行を他のテーブルに join する、cursor 経由で修正した行をアプリケーションに返す、修正した行をファイルにアウトプットする、などをとても簡単に行うことができます。
この拡張機能がない場合は、AFTER
または BEFORE TRIGGER
を定義して修正された行を他の(異なる)テーブルにコピーし、その別のテーブルのコンテンツを管理し(そして既存の updaters をハンドリングし)、UPDATE
文が実行された後にトリガーが挿入されたテーブルに別の SELECT
文を実行する必要があります。
これは update 文が行った変更をアウトプットするだけにもかかわらず、かなりの労力を要します。
そのため、この言語機能が SQL Anywhere version 12 で利用可能になったことをたいへんうれしく思います。
構文とセマンティクス
SQL Anywhere 12 におけるこの機能の文法は以下のとおりです:
- <table primary> ::= <table or query name> [ [ AS ] <correlation name> [ ( <derived column list> ) ] ]
- | other forms of table references …
- | ( <dml derived table> ) REFERENCING <result option>
- <dml derived table> ::= <delete statement>
- | <insert statement>
- | <merge statement>
- | <update statement>
- <result option> ::= OLD [AS] <correlation name>
- | FINAL [AS] <correlation name>
- | OLD [AS] <correlation name> FINAL [AS] <correlation name>
この構文は、DB2 で提供されているものとは 2 つの点で大きく異なります。
まず第一に UPDATE
または MERGE
文から新しい値と古い値の比較を計算するアプリケーションにおいて、構文を簡潔にしたいという思いがありました。
そして第二に、同じリクエストにおいてdml-derived-table を他のオブジェクトに簡単に joinできるようにしたいと考えたからです。
dml-derived-table の構文は以下のとおりです。
DESCRIBE の間、dml-derived-table は無視されます。
OPEN 時間で、DML update 文が最初に実行され、その文の影響を受けた行はテンポラリーテーブルにマテリアライズされます。
そのテンポラリーテーブルのスキーマ内のカラム名は修正されているテーブルから直接とられます – dml-derived-table が更新できるのは1つのテーブルのみです。
これらの値をREFERENCING 句で与えられた相関名で評価することで、参照することができます。
OLD
カラムには、更新オペレーションに含む行を発見するスキャンオペレーターによってみられるような値が含まれます。FINAL
カラムには、参照整合性チェックの実行、計算、デフォルトのカラムの充填、トリガーの実行の後の値 (FOR STATEMENT AFTER
トリガーを除く) が含まれます。
このような宣言では、簡単な制約があります。
INSERT
文では、特定できるのは FINAL
のみです。DELETE
文では、特定できるのは OLD
のみです。
しかしながら、UPDATE
と MERGE
文では、相関名のどちらも、または両方特定することができ、あらゆる更新行の古いまたは新しい値を簡単に比較することができます。文法上は、これらの名前を「相関名」として参照しますが、更新テーブルの異なる範囲の変数を参照することはないことに注意してください。むしろ、単に同じ文の中の古いカラム値と新しいカラム値の参照を行トリガー内の構文をミラーリングすることでシンプルにするための構文的なデバイスでしかありません。言い換えると、REFERENCING (OLD AS O FINAL AS F )
を特定すると、暗黙的に join predicate: O.rowid = F.rowid.が存在します。
例
クエリー内でdml-derived-table を使用して特定のデータベースの更新のインパクトをレポートする方法の簡単な例を以下に示します。サンプル Demo データベースを使用して、このクエリーで以下の問に答えます。
全製品を7%の価格アップで更新します。この影響を受けた製品で、2000年4月10日から2000年5月21日の間に出荷され、かつ注文数が36よりも大きいものをリストアップします。
(ちなみに : この Demo データベースに含まれているのは、2000 から 2001 までの日付のみのため、上記のクエリーを少し変更しています。しかし、読者の皆さんには一般的な意味を理解していただけるでしょう。)
以下は、DBISQL における、クエリー/update 文の見え方を示しています。
そして、以下はそのグラフィカルプランです。修正された行を含むテンポラリーテーブルの生成を表しているアクセスプランツリーの新しい “DML” オペレーターに注意してください。
ROW TRIGGER
構文 – を使用するもう一つの利点は、更新されたテーベルのためのユニークなカラム名の(もう1つの)セットでなくとも良い点です。単純に OLD
または FINAL
相関名でカラム名を評価するだけで十分です。
SQL Anywhere では、かなり前から join テーブル表現の UPDATE
文をサポートしていますが、現在のところは、最大で1つの更新テーブルを含むよう dml-derived-tables を制限しています。今後のバージョンでは、この制限を緩めるかもしれません。
===
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」
を入力してください。
不具合につきましては、サポート契約者様専用の問い合わせ方法にてお問い合わせください。
======================
ご購入に関するお問い合わせ
こちらよりお問い合わせください。