3

最初にいくつか検索しましたが、まだ質問があります。

遠く離れて、私が見つけた最良の答えはこのSOの答えにあります。要約:

SELECT * FROM TABLE WHERE ID = (SELECT MAX(ID) FROM TABLE);

私が知りたいのは、次の方法がうまく機能するかどうかです(変更するのが面倒で、たまたまそれが好きだからです)。

SELECT * FROM TABLE ORDER BY ID DESC LIMIT 1

私たちが持っているSQLite Autoincrementのドキュメントによると、

挿入時に ROWID が指定されていない場合、または指定された ROWID の値が NULL の場合、適切な ROWID が自動的に作成されます。通常のアルゴリズムでは、新しく作成された行に、挿入前の表の最大の ROWID よりも 1 大きい ROWID を指定します。テーブルが最初に空の場合、1 の ROWID が使用されます。【強調追加】

そしてさらに、

上記の通常の ROWID 選択アルゴリズムは、最大の ROWID 値を使用せず、最大の ROWID を持つテーブル内のエントリを削除しない限り、単調に増加する一意の ROWID を生成します。行を削除したり、最大の ROWID を持つ行を作成したりすると、以前に削除された行の ROWID が新しい行の作成時に再利用され、新しく作成された ROWID が厳密に昇順でなくなる可能性があります。 【強調追加】

提案した SQL ステートメントに関する私の質問は、最後の文から来ています。最大のROWIDが使用されたかどうかに関係なく、行を削除すると、以前に削除されたROWIDを再利用できることを示しているようです。最大の ROWID が (手動またはそれだけの数のレコードによって) 使用されないと仮定すると、レコードの削除についてのみ心配する必要があります。そのような場合、最初の SQLite ドキュメントの抜粋を見ると、私のクエリで問題が発生することはないように思えます。

誰かが確かに知っていますか?

私のクエリが気に入っているのは、select が 1 つしかないためです (ただし、order by を犠牲にして)。おそらく、小さな最適化に集中しすぎているのではないでしょうか?

編集: 実際、上記の SQLite ページを再検討すると、AUTOINCREMENT キーワードを使用すると、単調に増加する ROWID が保証されると思います。最後のセクションでは、それについて詳しく説明しています。

列の型が INTEGER PRIMARY KEY AUTOINCREMENT の場合、わずかに異なる ROWID 選択アルゴリズムが使用されます。新しい行に選択された ROWID は、同じテーブルに以前存在した最大の ROWID より少なくとも 1 大きいです。表にデータが含まれていない場合は、ROWID として 1 が使用されます。テーブルが可能な限り最大の ROWID を持つ行を以前に保持していた場合、新しい INSERT は許可されず、新しい行を挿入しようとすると SQLITE_FULL エラーで失敗します。

今はかなりはっきりしているようです。テーブルをいっぱいにすることはできません (最大 9223372036854775807)。

すみません、先にこの部分をすくい取っただけでした!

4

4 に答える 4

4

ここで、2 つのクエリの実行速度について少しメモしておきます。
約 15,000 行のテーブルで、そのうちの 1400 行を取得し、最後に入力された行を取得すると、次のような結果が得られました。

SELECT macAddr, time, onPeakTotalIn, onPeakTotalOut, offPeakTotalIn, offPeakTotalOut FROM trafficMon WHERE macAddr="02:d2:ee:aa:aa:aa" ORDER BY time DESC LIMIT 1;

CPU 時間: user 0.008124 sys 0.000000
仮想マシン ステップ: 58741
フルスキャン ステップ: 14156

SELECT macAddr, time, onPeakTotalIn, onPeakTotalOut, offPeakTotalIn, offPeakTotalOut FROM trafficMon WHERE id = (SELECT MAX(id) FROM trafficMon WHERE macAddr="02:d2:ee:aa:aa:aa");

CPU 時間: user 0.000295 sys 0.000000
仮想マシン ステップ: 49
フルスキャン ステップ: 3

ご覧のとおり、MAX(id) リソースを賢く実行する方がはるかに簡単で、実行にかかる時間も大幅に短縮されます。

0.008124s は常にバガーですが、MIPS ベースの組み込みデバイス (私の場合はルーター) で同じコマンドを実行すると、スクリプトで 20 ~ 30 倍のコマンドを実行し、他の多くのものと一緒に実行すると、すべて加算されます。

お役に立てば幸いです:)

ダッキー

于 2015-01-11T03:39:59.473 に答える
3

あなたが示す2つのクエリは同等です。

最後のレコードを返すかどうかは、「最後」の意味によって異なります。行を削除すると、最後に挿入された行を返すためにどちらのクエリにも依存できなくなります。

于 2012-08-01T19:44:44.577 に答える
1

まず、最後に挿入された行 ID を取得し、その行 ID から選択クエリによって最後に挿入されたレコードを取得する必要があります。

RowID = sqlite3_last_insert_rowid(sqlite3Database)

SELECT * FROM tableName where RowID=RowID

このselectステートメントは、最後に挿入されたレコードを提供します

このリンクで詳細を入手してください。

于 2015-01-11T05:39:13.140 に答える