Chèn Chèn nếu không tồn tại Câu lệnh trong SQLite


142

Tôi có một cơ sở dữ liệu SQLite. Tôi đang cố gắng chèn các giá trị ( users_id, lessoninfo_id) vào bảng bookmarks, chỉ khi cả hai không tồn tại trước đó trong một hàng.

INSERT INTO bookmarks(users_id,lessoninfo_id) 
VALUES(
    (SELECT _id FROM Users WHERE User='"+$('#user_lesson').html()+"'),
        (SELECT _id FROM lessoninfo 
        WHERE Lesson="+lesson_no+" AND cast(starttime AS int)="+Math.floor(result_set.rows.item(markerCount-1).starttime)+") 
        WHERE NOT EXISTS (
            SELECT users_id,lessoninfo_id from bookmarks 
            WHERE users_id=(SELECT _id FROM Users 
            WHERE User='"+$('#user_lesson').html()+"') AND lessoninfo_id=(
                SELECT _id FROM lessoninfo
                WHERE Lesson="+lesson_no+")))

Điều này đưa ra một lỗi cho biết:

lỗi db gần cú pháp.

Câu trả lời:


138

Nếu bạn có một bảng được gọi là bản ghi nhớ có hai cột idtextbạn sẽ có thể làm như thế này:

INSERT INTO memos(id,text) 
SELECT 5, 'text to insert' 
WHERE NOT EXISTS(SELECT 1 FROM memos WHERE id = 5 AND text = 'text to insert');

Nếu một bản ghi đã chứa một hàng textbằng 'văn bản cần chèn' và idbằng 5, thì thao tác chèn sẽ bị bỏ qua.

Tôi không biết nếu điều này sẽ làm việc cho truy vấn cụ thể của bạn, nhưng có lẽ nó cung cấp cho bạn một gợi ý về cách tiến hành.

Tôi sẽ khuyên bạn thay vì thiết kế bảng của bạn để không cho phép trùng lặp như được giải thích @CLs answerdưới đây.


435

Nếu bạn không bao giờ muốn có các bản sao, bạn nên khai báo đây là một ràng buộc bảng:

CREATE TABLE bookmarks(
    users_id INTEGER,
    lessoninfo_id INTEGER,
    UNIQUE(users_id, lessoninfo_id)
);

(Khóa chính trên cả hai cột sẽ có cùng tác dụng.)

Sau đó, có thể nói với cơ sở dữ liệu rằng bạn muốn âm thầm bỏ qua các bản ghi sẽ vi phạm một ràng buộc như vậy :

INSERT OR IGNORE INTO bookmarks(users_id, lessoninfo_id) VALUES(123, 456)

12
Cách tối ưu để lấy ID của hàng mới được chèn hoặc hàng đã có sẵn là gì, vì vậy tôi có thể chèn nó vào một bảng khác có khóa ngoại đối với hàng này? ví dụ như tôi có hai bảng person (id, name unique)cat (person_id, name unique)và tôi muốn chèn nhiều cặp (person_name, cat_name)?
Aur Saraf

2
Chỉ có thể đọc ID của một hàng hiện có với truy vấn CHỌN. Nhưng đây là một câu hỏi khác nhau.
CL.

1
Có lẽ thêm ON CONFLICT IGNOREvào CREATE TABLEsẽ tiện dụng hơn một chút
defhlt

1
@ rightaway717 "Bỏ qua" có nghĩa là không có gì xảy ra; Câu hỏi này không liên quan gì đến việc cập nhật.
CL.

1
@ Hack06 Android insert () hoạt động khác nhau; bạn nên thay thế nó bằng insertOrThrow () hoặc insertWithOnConflict () .
CL.

21

Đối với một cột duy nhất, sử dụng này:

INSERT OR REPLACE INTO table () values();

Để biết thêm thông tin, xem: sqlite.org/lang_insert


Điều này không làm việc cho tôi. nó luôn chèn như khi chèn hoặc thay thế vào các giá trị my_table (col1, col2) ('1', '2'); sẽ thêm nhiều hàng của 1 2
Peter Moore

Tôi có thể thêm rằng nó hoạt động tốt nếu đặt ràng buộc Unique(col1,col2)và bạn cũng có col3, bởi vì việc chèn hoặc bỏ qua sẽ không thành công khi điều này sẽ cập nhật col3 lên giá trị mới. insert or replace into my_table values('1','2','5')thay thế một hàng'1','2','3'
Peter Moore

4
insert into bookmarks (users_id, lessoninfo_id)

select 1, 167
EXCEPT
select user_id, lessoninfo_id
from bookmarks
where user_id=1
and lessoninfo_id=167;

Đây là cách nhanh nhất.

Đối với một số công cụ SQL khác, bạn có thể sử dụng bảng Dummy chứa 1 bản ghi. ví dụ:

select 1, 167 from ONE_RECORD_DUMMY_TABLE
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.