SQLite의 "존재하지 않으면 삽입"문


143

SQLite 데이터베이스가 있습니다. 행에 이전에 둘 다 존재하지 않는 경우에만 table에 값 ( users_id, lessoninfo_id) 을 삽입하려고합니다 bookmarks.

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+")))

다음과 같은 오류가 발생합니다.

구문 근처의 db 오류.

답변:


138

당신이 두 개의 열이있는 테이블라는 메모가있는 경우 id그리고 text당신은 다음과 같이 할 수 있어야한다 :

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');

레코드 text에 '삽입 할 텍스트'와 id같고 5 와 같은 행이 이미 포함되어 있으면 삽입 작업이 무시됩니다.

이것이 귀하의 특정 쿼리에 효과가 있는지는 모르겠지만 진행 방법에 대한 힌트를 줄 수 있습니다.

대신 @CLs answer아래 설명과 같이 중복이 허용되지 않도록 테이블을 디자인하는 것이 좋습니다 .


436

중복을 원하지 않으면이를 테이블 제약 조건으로 선언해야합니다.

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

(두 열의 기본 키는 동일한 효과를 갖습니다.)

그런 다음 이러한 제한 조건을 위반하는 레코드자동으로 무시 하고 싶다고 데이터베이스에 알릴 수 있습니다 .

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

12
그런 다음 새로 삽입 된 행의 ID 또는 기존 행의 ID를 얻는 가장 좋은 방법은 무엇입니까? 그래서 외래 키가있는 다른 테이블에 삽입 할 수 있습니까? 예를 들어 두 개의 테이블이 person (id, name unique)있고 cat (person_id, name unique)많은 쌍을 삽입하고 싶습니다 (person_name, cat_name).
Aur Saraf

2
기존 행의 ID를 읽는 것은 SELECT 쿼리를 통해서만 가능합니다. 그러나 이것은 다른 질문입니다.
CL.

1
아마도 추가 ON CONFLICT IGNORE하는 CREATE TABLE것이 좀 더 편리 할 것입니다.
defhlt

1
@ rightaway717 "무시"는 아무 일도 일어나지 않음을 의미합니다. 이 질문은 업데이트와 관련이 없습니다.
CL.

1
@ Hack06 Android의 insert ()는 다르게 동작합니다. insertOrThrow () 또는 insertWithOnConflict ()로 바꿔야합니다 .
CL.

21

고유 한 열의 경우 다음을 사용하십시오.

INSERT OR REPLACE INTO table () values();

자세한 정보는 sqlite.org/lang_insert를 참조하십시오.


이것은 나를 위해 작동하지 않습니다. 항상 삽입하거나 my_table (col1, col2) values ​​( '1', '2')에 바꾸는 것처럼 삽입합니다. 1 2의 행을 여러 개 추가합니다
Peter Moore

제약 조건이 적용되고 Unique(col1,col2)col3 이있는 경우 잘 작동한다고 덧붙일 수 있습니다 . 삽입 또는 무시가 col3을 새 값으로 업데이트하는 위치에서 삽입 또는 무시가 실패하기 때문입니다. insert or replace into my_table values('1','2','5')행 교체'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;

이것이 가장 빠른 방법입니다.

다른 SQL 엔진의 경우 1 레코드를 포함하는 더미 테이블을 사용할 수 있습니다. 예 :

select 1, 167 from ONE_RECORD_DUMMY_TABLE
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.