SQLite INSERT-重複キー更新(UPSERT)


98

MySQLには次のようなものがあります。

INSERT INTO visits (ip, hits)
VALUES ('127.0.0.1', 1)
ON DUPLICATE KEY UPDATE hits = hits + 1;

この機能がSQLiteに存在しないことを知っている限り、2つのクエリを実行せずに同じ効果を得る方法があるかどうかを知りたいです。また、これが不可能な場合、あなたは何を好みますか:

  1. SELECT +(INSERTまたはUPDATE)または
  2. UPDATE(+ UPDATEが失敗した場合は INSERT )

回答:



117
INSERT OR IGNORE INTO visits VALUES ($ip, 0);
UPDATE visits SET hits = hits + 1 WHERE ip LIKE $ip;

これには、「ip」列にUNIQUE(またはPRIMARY KEY)制約が必要です。


編集:別の優れたソリューション:https : //stackoverflow.com/a/4330694/89771


2
参考までに、REPLACEオプションではありません。
Alix Axel

1
「別の素晴らしいソリューション」のリンクについては、私も同じ質問に異なる答えを検討する:stackoverflow.com/a/418988/3650835
KayakinKoder

19

私は好むUPDATE (+ INSERT if UPDATE fails)。コードが少ない=バグが少ない。


1
ありがとう!@Sam(stackoverflow.com/questions/418898/…)はあなたに同意するようです。私もこのアプローチを好みます。
Alix Axel

@スミス私はプレーンなUPDATEおよびINSERTステートメントを使用して戻り値をチェックすることを意味しました。
codeholic、2013年

これには原子性がないため、間に他のプロセスが挿入されていると、INSERTが失敗する可能性があります。
ロビンラヴァレ

7

現在の答えはsqlite OR mysqlでのみ機能します(ORを使用するかどうかによって異なります)。したがって、dbmsとの互換性が必要な場合は、次のようにします...

REPLACE INTO `visits` (ip, value) VALUES ($ip, 0);

3
受け入れられた答えはSQLiteで機能します(それが私の目的でした)。REPLACESQLiteでも動作しますが、MySQLでは常にカウンタが0にリセットされます。クエリは移植可能ですが、最終結果は大きく異なります。
Alix Axel

そうですね、OPはポータブルなものを探していると思いました。REPACE INTOがすべてのケースで機能するわけではないことに気付きました。特にPKの保持が必要な場合ですが、多くのケースでは機能します。
ジェイコブトーマソン

データを破棄する代わりに完全に失敗するのは機能であり、バグではありません。
東武

-4

memcachedは単一の値(アクセス数)を格納する単一のキー(IPアドレス)であるため、これにはmemcachedを使用する必要があります。アトミック増分関数を使用して、「競合」状態がないことを確認できます。

これはMySQLよりも高速で、負荷を軽減するため、MySQLは他のことに集中できます。


データがそれほど重要でなければ、はい。ただし、これが、多くのIPがサービスにアクセスしているビジーなサイトで使用されている場合、memcachedインスタンスがいっぱいになり、一部のコンテンツがドロップされる可能性があります。(必要な場合)。memcachedの内容をバックアップすることも、興味深いものになるだろう
エリオット・フォスター

@ElliotFoster Memcachedは、RAMと同じ量のデータを処理できます(永続性が必要な場合は、redisまたはmembaseも使用します)。1日に100万人を超えるビジターがいる場合、おそらくmemcacheインスタンスに30MB以上のRAMを与える余裕があります(これがデフォルトだと思います)。ただし、SQLiteやMySQLよりもはるかに高い負荷を、それが与えるメモリの量で確実に処理できます。比較することはできません。
Xeoncross、2011年

私のコメントは素晴らしいツールだと思うので、memcacheに対する投票と間違えないでください。redisと同様(私はmembaseを使用していないため、話せません。)ただし、me​​mcache / redisは最も信頼できるストアではありません。はい、redisには永続性がありますが、データは一定の間隔(最後に確認した)でディスクに永続化され、memcacheはまったく存在しません。私が言ったように、データが重要ではない(または簡単に再現できる)場合、memcacheとcompanyは素晴らしいです。元の投稿はsqliteについても尋ねていましたが、これはMySQLとは非常に異なり、おそらく他の方法で制限されていることを意味します。
エリオット・フォスター

Redisを構成して、データを必要なだけ高速に維持できます(秒数Xまたは変更数Y)。
バッファロー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.