Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 12.0.1 » Mobile Link クライアント管理 » Mobile Link 用 SQL Anywhere クライアント » スクリプト化されたアップロード » チュートリアル:スクリプト化されたアップロードの使用

 

レッスン 4:更新の処理

このレッスンは、受講者がこれまでのすべてのレッスンを終了していることを前提としています。 レッスン 1:統合データベースの作成を参照してください。

アップロードを処理するには、アップロード構築中、開始進行状況値に基づいて正しい更新前イメージを使用する必要があります。

 ♦ 更新の処理
  1. リモートデータベースに接続された Interactive SQL のインスタンスを使用して、更新されたローの更新前イメージを保持するテーブルを作成します。スクリプト化されたアップロードを生成するときには、更新前イメージが使用されます。

    CREATE TABLE employee_preimages (
       id           unsigned integer NOT NULL,
       name         varchar( 256),
       salary       numeric( 9, 2 ),
       img_time     timestamp default CURRENT TIMESTAMP,
       primary key( id, img_time )
    );
  2. 次に、各ローが更新されるときに、更新前イメージを保存するトリガーを作成します。挿入トリガーと同様、このトリガーもダウンロードでは起動しません。

    CREATE TRIGGER emp_upd AFTER UPDATE OF name,salary ON employee
       REFERENCING OLD AS oldrow
       FOR EACH ROW
    BEGIN
       INSERT INTO employee_preimages ON EXISTING SKIP VALUES(
          oldrow.id, oldrow.name, oldrow.salary, CURRENT TIMESTAMP );
    END;

    このトリガーは、ローが更新されるたびに更新前イメージを保存します (ただし、2 つの更新が非常に近く、タイムスタンプが同じ場合を除く)。これは一見、無駄に見えるので、ローの更新前イメージがテーブルにない場合のみ保存し、sp_hook_dbmlsync_upload_end フックに依存して、更新前イメージがアップロードされた後に削除しがちです。

    しかし、sp_hook_dbmlsync_upload_end フックは、この目的では確実ではありません。アップロードを送信した後で受信確認される前に、ハードウェアまたはソフトウェアの障害により dbmlsync が停止した場合、フックが呼び出されない可能性があります。その結果、ローが正常にアップロードされても、ローは更新前イメージ テーブルから削除されません。また、通信障害が発生すると、dbmlsync はサーバーからアップロードの受信確認を受信できない場合があります。この場合、フックに渡されるアップロードステータスは「不明」になります。このステータスでは、フックは、更新前イメージテーブルがクリーンアップされたのかそのままなのかを判別できません。複数の更新前イメージを保存すると、アップロードが構築されるときに、開始進行状況値に基づいて正しい更新前イメージが常に選択されます。

  3. 次に、更新を処理するアップロードプロシージャーを作成します。



    CREATE PROCEDURE employee_update()
    RESULT(
           preimage_id  unsigned integer,
           preimage_name varchar( 256),
           preimage_salary numeric( 9,2 ),
           postimage_id  unsigned integer,
           postimage_name varchar( 256),
           postimage_salary numeric( 9,2 )
          )
    BEGIN
        DECLARE start_time timestamp;
    
        SELECT value
        INTO start_time
        FROM #hook_dict
        WHERE name = 'start progress as timestamp';
    
        // Upload as an update all rows that have been updated since 
        // start_time that were not newly inserted or deleted.
        SELECT ep.id, ep.name, ep.salary, e.id, e.name, e.salary
        FROM employee e JOIN employee_preimages ep 
            ON ( e.id = ep.id )
        // Do not select rows inserted since the start time. These should be
        // uploaded as inserts.
        WHERE insert_time <= start_time 
          // Do not upload deleted rows.
          AND NOT EXISTS( SELECT id FROM employee_delete ed  WHERE ed.id = e.id )
          // Select the earliest pre-image after the start time.
          AND ep.img_time = ( SELECT MIN( img_time )
                FROM employee_preimages
                WHERE id = ep.id
                AND img_time > start_time );
    END;

    このストアドプロシージャーは、他のスクリプトの 2 倍のカラムを持つ結果セットを 1 つ返します。これには、更新前イメージ (Mobile Link サーバーから最後に受信したローと、正常にアップロードされたローの値) と更新後イメージ (統合データベースに入力される値) が含まれます。

    更新前イメージは、start_progress 後に記録された employee_preimages の一番最初の値セットです。この例では、削除されてから再度挿入された既存のローは、正しく処理されません。より完全なソリューションでは、これらのローは更新としてアップロードされます。

  4. レッスン 5:削除の処理に進みます。