2010-04-26 38 views
74

MySQL có một cái gì đó như thế này:SQLite INSERT - ON DUPLICATE CẬP NHẬT KEY

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

Theo như tôi biết tính năng này không tồn tại trong SQLite, những gì tôi muốn biết là nếu có bất kỳ cách nào để lưu trữ cùng một hiệu ứng mà không phải thực thi hai truy vấn. Ngoài ra, nếu điều này là không thể, làm những gì bạn thích:

  1. CHỌN + (INSERT hoặc UPDATE) hoặc
  2. UPDATE (+ INSERT nếu CẬP NHẬT thất bại)

Trả lời

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

Điều này yêu cầu cột "ip" phải có một hạn chế UNIQUE (hoặc PRIMARY KEY).


EDIT: Một giải pháp tuyệt vời khác: https://stackoverflow.com/a/4330694/89771.

+2

Chỉ để lưu nội dung, 'REPLACE' không phải là một lựa chọn. –

+1

Liên quan đến liên kết "giải pháp tuyệt vời khác", tôi cũng sẽ xem xét một câu trả lời khác cho cùng một câu hỏi: http://stackoverflow.com/a/418988/3650835 – KayakinKoder

16

Tôi thích UPDATE (+ INSERT if UPDATE fails). Ít mã hơn = ít lỗi hơn.

+0

Cảm ơn! @Sam (http://stackoverflow.com/questions/418898/sqlite-upsert-not-insert-or-replace/418988#418988) dường như đồng ý với bạn. Tôi cũng thích cách tiếp cận này. –

+1

@codeholic nơi tôi có thể nhận cú pháp cho phương thức này – Smith

+0

@Smith Tôi có nghĩa là sử dụng các câu lệnh UPDATE và INSERT đơn giản và kiểm tra giá trị trả về. – codeholic

-3

Bạn nên sử dụng memcached vì đây là một khóa duy nhất (địa chỉ IP) lưu trữ một giá trị duy nhất (số lượt truy cập). Bạn có thể sử dụng hàm tăng nguyên tử để đảm bảo không có điều kiện "đua".

Nó nhanh hơn MySQL và lưu tải để MySQL có thể tập trung vào những thứ khác.

+0

Nếu dữ liệu không quan trọng, có. Tuy nhiên, nếu điều này đang được sử dụng trên một trang web bận rộn nơi nhiều IP đang nhấn dịch vụ, các thể hiện được ghi nhớ có thể bị đầy và gây ra một số nội dung bị xóa. Sao lưu nội dung memcached cũng sẽ rất thú vị (nếu được yêu cầu.) –

+0

@ElliotFoster Memcached có thể xử lý càng nhiều dữ liệu như RAM bạn ném vào nó (nếu bạn muốn sự thừa kế cũng sau đó sử dụng redis hoặc membase). Nếu bạn đang nhận được hơn 1 triệu khách truy cập ngày thì bạn có thể đủ khả năng cho ví dụ memcache của bạn hơn 30MB ram (đó là mặc định tôi nghĩ). Tuy nhiên, nó chắc chắn có thể xử lý một tải cao hơn nhiều so với SQLite và MySQL cho số lượng bộ nhớ mà bạn cung cấp cho nó - không có bất kỳ sự so sánh nào. – Xeoncross

+0

Xin đừng nhầm lẫn bình luận của tôi như một lá phiếu chống lại memcache, vì tôi nghĩ đó là một công cụ tuyệt vời. Như redis (Tôi không thể nói cho membase, như tôi đã không sử dụng nó.) Tuy nhiên, memcache/redis không phải là các cửa hàng đáng tin cậy nhất. Có, redis có kiên trì, nhưng dữ liệu được lưu vào đĩa trên một khoảng thời gian (cuối cùng tôi nhìn) và memcache không phải ở tất cả. Như tôi đã nói, nếu dữ liệu không quan trọng (hoặc có thể được sao chép dễ dàng) thì memcache và công ty rất tuyệt. Bài đăng gốc cũng hỏi về sqlite, rất khác với MySQL và có thể có nghĩa là chúng bị giới hạn theo những cách khác. –

5

Câu trả lời hiện tại sẽ chỉ hoạt động trong sqlite OR mysql (tùy thuộc vào việc bạn sử dụng OR hay không). Vì vậy, nếu bạn muốn tương thích chéo dbms, sau đây sẽ làm ...

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

Câu trả lời được chấp nhận hoạt động trên SQLite (đó là mục tiêu của tôi). 'REPLACE' cũng sẽ hoạt động trên SQLite, nhưng trên MySQL nó sẽ luôn đặt lại bộ đếm là 0 - trong khi truy vấn sẽ được di chuyển, kết quả cuối cùng sẽ khác nhau rất nhiều. –

+0

Bạn nói đúng, tôi nghĩ OP đang tìm kiếm thứ gì đó di động. Tôi nhận ra REPLACE INTO sẽ không hoạt động với tất cả các trường hợp, đặc biệt là nơi cần bảo quản PK, nhưng sẽ có nhiều trường hợp. –

+0

Thất bại sạch sẽ thay vì loại bỏ dữ liệu là một tính năng, không phải là lỗi. – Tobu

Các vấn đề liên quan