0

一意の列「orderby」によって順序が維持される順序付きリストの中央にエントリを移動したいと思います。値をリストの中央に移動するときは、orderby値を指定します。値がすでに取得されている場合は、移動の方向に応じて、古い行のorderbyを1つインクリメントまたはデクリメントする必要があります。

テストの目的で、私はこのテーブルを持っています:

CREATE TABLE test(
orderby integer,
UNIQUE(orderby) )

そして、私は現在、次のトリガーを持っています:

CREATE TRIGGER [test_insert] 
BEFORE UPDATE OF [orderby]  
ON [test] 
FOR EACH ROW 
BEGIN 

UPDATE test
SET orderby = orderby + 1
WHERE NEW.orderby = orderby;

END

ただし、これは、トリガーによって作成されたorderby値が使用されていない場合にのみ機能します。

つまり、を実行するUPDATE test SET orderby = 2 WHERE orderby = 1と、orderby値が{1のテーブルで機能します。2}ですが、値が{1;のテーブルではありません。2; 3}

どうすればこれを解決できますか?それとも完全に違うのでしょうか?

編集:これを機能させることができない場合は、範囲内のすべてのorderby-sをインクリメントするオプションが常にあると思いますが、それでもこれを機能させたいので、値またはorderbyのギャップを使用できますより効率的になります。

4

1 に答える 1

0

編集:欲求が明確になったので、元の答えを置き換えました。

一意性違反の後にBEFOREトリガーでさえ起動するため、フィールドを一意として定義することはできません。したがって、より安全なAFTERを使用してください。

これがあなたが望むと思うコードであり、その後にいくつかのテストアップデートが続きます。

CREATE TABLE test(pk char primary key,
                  orderby integer);

CREATE TRIGGER test_insert 
  AFTER UPDATE OF orderby ON test 
  BEGIN
    UPDATE test
       set orderby = orderby + 1
     where test.orderby >= NEW.orderby
       and test.pk != NEW.pk;
  END;

insert into test (pk, orderby) values ("a", 1);
insert into test (pk, orderby) values ("b", 2);
insert into test (pk, orderby) values ("c", 3);

select * from test;

update test set orderby=1 where pk='c';
select * from test order by orderby";
update test set orderby=2 where pk='b';
select * from test order by orderby;
update test set orderby=4 where pk='a';
select * from test order by orderby;
于 2013-01-04T01:01:56.780 に答える