競合を解決するのに resolve_conflict スクリプトを使用する代わりに、upload_update スクリプトでストアド・プロシージャを呼び出すこともできます。この方法では、プログラムで競合の検出と解決の両方を行う必要があります。
ストアド・プロシージャでは、すべてのカラムを含んでいるが、更新前イメージの (古い) 値を使用する WHERE 句のある upload_update スクリプトのフォーマットを使用してください。
以下は、upload_update スクリプトの例です。
{CALL UpdateProduct( {ml o.id}, {ml o.name}, {ml o.desc}, {ml r.name}, {ml r.desc} ) } |
以下は、UpdateProduct ストアド・プロシージャの例です。
CREATE PROCEDURE UpdateProduct( @id INTEGER, @preName VARCHAR(20), @preDesc VARCHAR(200), @postName VARCHAR(20), @postDesc VARCHAR(200) ) BEGIN UPDATE product SET name = @postName, description = @postDesc WHERE id = @id AND name = @preName AND description = @preDesc IF @@rowcount=0 THEN // A conflict occurred: handle resolution here. END IF END |
この方法は、resolve_conflict スクリプトによる競合の解決よりも管理が簡単です。それは、管理するスクリプトが 1 つだけで、すべての論理が 1 つのストアド・プロシージャに含まれているからです。ただし、テーブル・カラムが NULL 入力可の場合、または BLOB や CLOB が含まれている場合には、ストアド・プロシージャのコードが複雑になる可能性があります。また、Mobile Link 統合データベースとしてサポートされている RDBMS の一部には、ストアド・プロシージャに渡すことができる値のサイズに制限があります。
次の項を参照してください。
次のストアド・プロシージャ sp_update_my_customer には、競合を検出し解決するための論理が定義されています。このストアド・プロシージャは古いカラム値と新しいカラム値を受け入れます。この例は SQL Anywhere の機能を使用します。スクリプトは次のように実装できます。
{CALL sp_update_my_customer( {ml o.cust_1st_pk}, {ml o.cust_2nd_pk}, {ml o.first_name}, {ml o.last_name}, {ml o.nullable_col}, {ml o.last_modified}, {ml r.first_name}, {ml r.last_name}, {ml r.nullable_col}, {ml r.last_modified} )} CREATE PROCEDURE sp_update_my_customer( @cust_1st_pk INTEGER, @cust_2nd_pk INTEGER, @old_first_name VARCHAR(100), @old_last_name VARCHAR(100), @old_nullable_col VARCHAR(20), @old_last_modified DATETIME, @new_first_name VARCHAR(100), @new_last_name VARCHAR(100), @new_nullable_col VARCHAR(20), @new_last_modified DATETIME ) BEGIN DECLARE @current_last_modified DATETIME; // Detect a conflict by checking the number of rows that are // affected by the following update. The WHERE clause compares // old values uploaded from the remote to current values in // the consolidated database. If the values match, there is // no conflict. The COALESCE function returns the first non- // NULL expression from a list, and is used in this case to // compare values for a nullable column. UPDATE my_customer SET first_name = @new_first_name, last_name = @new_last_name, nullable_col = @new_nullable_col, last_modified = @new_last_modified WHERE cust_1st_pk = @cust_1st_pk AND cust_2nd_pk = @cust_2nd_pk AND first_name = @old_first_name AND last_name = @old_last_name AND COALESCE(nullable_col, '') = COALESCE(@old_nullable_col, '') AND last_modified = @old_last_modified; ... // Use the @@rowcount global variable to determine // the number of rows affected by the update. If @@rowcount=0, // a conflict has occurred. In this example, the database with // the most recent update wins the conflict. If the consolidated // database wins the conflict, it retains its current values // and no action is taken. IF( @@rowcount = 0 ) THEN // A conflict has been detected. To resolve it, use business // logic to determine which values to use, and update the // consolidated database with the final values. SELECT last_modified INTO @current_last_modified FROM my_customer WITH( HOLDLOCK ) WHERE cust_1st_pk=@cust_1st_pk AND cust_2nd_pk=@cust_2nd_pk; IF( @new_last_modified > @current_last_modified ) THEN // The remote has won the conflict: use the values it // uploaded. UPDATE my_customer SET first_name = @new_first_name, last_name = @new_last_name, nullable_col = @new_nullable_col, last_modified = @new_last_modified WHERE cust_1st_pk = @cust_1st_pk AND cust_2nd_pk = @cust_2nd_pk; END IF; END IF; END; |
次の項を参照してください。
Copyright © 2009, iAnywhere Solutions, Inc. - SQL Anywhere 11.0.1 |