コンテキスト:次の
ようなテーブルを持つSQLiteデータベースがあります:
CREATE TABLE items (item TEXT, position INTEGER)
このテーブルには、数百万のエントリが含まれています。列position
に索引が付けられます。
私のフロントエンドは、列に適用する一連の更新を作成することがありposition
ます。更新対象の行は、ID によって識別されません。これは、更新が広範囲の項目に対して行われる可能性があり、関連するすべての ID をリストすると非常にコストがかかる可能性があるためです。たとえば、「位置 >= 500 & 位置 <= 10000 に +10 を追加する」-「位置 >= 100000 & 位置 <= 100003 に -3 を追加する」などの更新アクションをまとめて実行できます。
問題: 更新の束の更新の条件付き位置はすべて、束ねられた更新の前の位置の値に基づいています。一括更新の各更新アクションを順次実行すると、更新の 1 つの後に「重複」の問題が発生する可能性があります (実際には存在します)。
例によって:
item | position
it1 | 1
it2 | 2
it3 | 3
it4 | 4
it5 | 5
it6 | 6
it7 | 7
この一連の更新がある場合:「位置 >= 5 & 位置 <= 6 に + 2 を追加」-「位置 >= 3 & 位置 <= 4 に - 2 を追加」これを次の SQLite クエリに変換します。
UPDATE items SET position=position-2 WHERE position >= 5 AND position <= 6
UPDATE items SET position=position+2 WHERE position >= 3 AND position <= 4
私はこの結果を得るつもりです:
it1 | 1
it2 | 2
it3 | 5
it4 | 6
it5 | 5
it6 | 6
it7 | 7
私が望むものの代わりに、それは言うことです:
it1 | 1 { it1 | 1 }
it2 | 2 { it2 | 2 }
it3 | 5 { it5 | 3 }
it4 | 6 ===> { it6 | 4 }
it5 | 3 { it3 | 5 }
it6 | 4 { it4 | 6 }
it7 | 7 { it7 | 7 }
これは、ある操作から別の操作への「重複」によるものです。
私の最初のアイデアは、次のように CASE を使用することでした:
UPDATE items SET position=CASE WHEN position >= 5 AND position <= 6 THEN position-2 WHEN position >= 3 AND position <= 4 THEN position+2 ELSE position END
このソリューションは正常に機能しますが、主要な関係者が更新に関与していなくても、SQLite がテーブルの何百万ものエントリに対してこれを実行しているように見えるため、非常に遅いです。
だから私はこれを次のように変更しました:
UPDATE items SET position=CASE WHEN position >= 5 AND position <= 6 THEN position-2 WHEN position >= 3 AND position <= 4 THEN position+2 ELSE position END WHERE (position >= 5 AND position <= 6) OR (position >= 3 AND position <= 4)
このソリューションは問題なく動作し、SQLite は関連する行でのみ更新を実行するため、非常に高速です。
質問 : 1 回の更新で 10 回、または 100 回の更新アクションを行うことができるため、クエリが非常に大きくなる可能性があり、これはあまり見栄えがよくありません...「美しい」/「素敵」。
これを処理するためのより美しい方法があると思いますか? SQLite は、影響を受ける行を最初に選択することでいくつかの「UPDATE」クエリを実行し、その後行を効果的に更新できますか?
アイデア?考え ?
どうもありがとうございました !