ข้อ จำกัด ของตาราง SQLite - ไม่ซ้ำกันในหลายคอลัมน์


179

ฉันสามารถหา "ชาร์ต" ไวยากรณ์บนเว็บไซต์ SQLite แต่ไม่มีตัวอย่างและรหัสของฉันล้มเหลว ฉันมีตารางอื่นที่มีข้อ จำกัด ที่ไม่ซ้ำกันในคอลัมน์เดียว แต่ฉันต้องการเพิ่มข้อ จำกัด ในตารางในสองคอลัมน์ นี่คือสิ่งที่ฉันมีที่ทำให้ SQLiteException พร้อมข้อความ "ข้อผิดพลาดทางไวยากรณ์"

CREATE TABLE name (column defs) 
UNIQUE (col_name1, col_name2) ON CONFLICT REPLACE

ฉันทำสิ่งนี้ตามสิ่งต่อไปนี้:

ตาราง จำกัด

เพื่อความชัดเจนเอกสารในลิงก์ที่ฉันระบุบอกว่าCONTSTRAINT nameควรมาก่อนคำจำกัดความของฉัน

สิ่งที่อาจนำไปสู่การแก้ปัญหา แต่ก็คือสิ่งใดก็ตามที่เป็นไปตามคำจำกัดความของคอลัมน์ที่ฉันใส่วงเล็บคือสิ่งที่ดีบักเกอร์บ่น

ถ้าฉันใส่

...last_column_name last_col_datatype) CONSTRAINT ...

ข้อผิดพลาดอยู่ใกล้กับ "CONSTRAINT": ข้อผิดพลาดทางไวยากรณ์

ถ้าฉันใส่

...last_column_name last_col_datatype) UNIQUE ...

ข้อผิดพลาดอยู่ใกล้กับ "UNIQUE": ข้อผิดพลาดทางไวยากรณ์


1
UNIQUE ไม่มีเครื่องหมายจุลภาคหายไปก่อนที่จะเริ่ม ..
Majid Bashir

คำตอบ:


345

ใส่การประกาศ UNIQUE ภายในส่วนคำจำกัดความของคอลัมน์ ตัวอย่างการทำงาน:

CREATE TABLE a (
    i INT,
    j INT,
    UNIQUE(i, j) ON CONFLICT REPLACE
);

6
คำตอบที่ดี +1 สิ่งนี้สร้างไวยากรณ์ให้ฉันใช้วิธีการแทรกแบบปกติหรือไม่และ insertWithOnConflict ด้วยการตั้งค่าสถานะ SQLiteDatabase.CONFLICT_REPLACE
Oleg Belousov

3
ฉันใช้ON CONFLICT IGNORE(ยังไม่ได้ลองแทนที่) ด้วยคอลัมน์มากกว่า 2 คอลัมน์ แต่ฉันไม่เห็นมันเป็นไปตามข้อ จำกัด ที่ไม่ซ้ำใครมันแค่เพิ่มความซ้ำซ้อน
Michael

5
เห็นได้ชัดเพราะฉันมีคอลัมน์เป็นศูนย์และที่เพิ่งยิงตรวจสอบที่ไม่ซ้ำกันออกไปนอกหน้าต่าง
Michael

ระวังการใช้ON CONFLICT REPLACEอาจไม่ใช่สิ่งที่คุณต้องการ - มันจะลบแถวที่มีอยู่แล้วเพื่ออนุญาตให้แทรกแถวใหม่ โดยปกติฉันต้องการยกเลิกหรือย้อนกลับการละเมิดข้อ จำกัด SQLite ON ข้อขัดแย้ง
karmakaze

9

ไวยากรณ์ของคุณไม่ตรงกับลิงก์ที่คุณระบุซึ่งระบุ:

 CREATE TABLE name (column defs) 
    CONSTRAINT constraint_name    -- This is new
    UNIQUE (col_name1, col_name2) ON CONFLICT REPLACE

ตอนแรกฉันทำอย่างนั้น ... ไม่ทำงาน ฉันลองอีกครั้งในกรณีที่ ... ยังไม่ได้ผล
รวย

1

ระวังวิธีที่คุณกำหนดตารางสำหรับคุณจะได้รับผลลัพธ์ต่าง ๆ ในส่วนแทรก พิจารณาดังต่อไปนี้



CREATE TABLE IF NOT EXISTS t1 (id INTEGER PRIMARY KEY, a TEXT UNIQUE, b TEXT);
INSERT INTO t1 (a, b) VALUES
    ('Alice', 'Some title'),
    ('Bob', 'Palindromic guy'),
    ('Charles', 'chucky cheese'),
    ('Alice', 'Some other title') 
    ON CONFLICT(a) DO UPDATE SET b=excluded.b;
CREATE TABLE IF NOT EXISTS t2 (id INTEGER PRIMARY KEY, a TEXT UNIQUE, b TEXT, UNIQUE(a) ON CONFLICT REPLACE);
INSERT INTO t2 (a, b) VALUES
    ('Alice', 'Some title'),
    ('Bob', 'Palindromic guy'),
    ('Charles', 'chucky cheese'),
    ('Alice', 'Some other title');

$ sqlite3 test.sqlite
SQLite version 3.28.0 2019-04-16 19:49:53
Enter ".help" for usage hints.
sqlite> CREATE TABLE IF NOT EXISTS t1 (id INTEGER PRIMARY KEY, a TEXT UNIQUE, b TEXT);
sqlite> INSERT INTO t1 (a, b) VALUES
   ...>     ('Alice', 'Some title'),
   ...>     ('Bob', 'Palindromic guy'),
   ...>     ('Charles', 'chucky cheese'),
   ...>     ('Alice', 'Some other title') 
   ...>     ON CONFLICT(a) DO UPDATE SET b=excluded.b;
sqlite> CREATE TABLE IF NOT EXISTS t2 (id INTEGER PRIMARY KEY, a TEXT UNIQUE, b TEXT, UNIQUE(a) ON CONFLICT REPLACE);
sqlite> INSERT INTO t2 (a, b) VALUES
   ...>     ('Alice', 'Some title'),
   ...>     ('Bob', 'Palindromic guy'),
   ...>     ('Charles', 'chucky cheese'),
   ...>     ('Alice', 'Some other title');
sqlite> .mode col
sqlite> .headers on
sqlite> select * from t1;
id          a           b               
----------  ----------  ----------------
1           Alice       Some other title
2           Bob         Palindromic guy 
3           Charles     chucky cheese   
sqlite> select * from t2;
id          a           b              
----------  ----------  ---------------
2           Bob         Palindromic guy
3           Charles     chucky cheese  
4           Alice       Some other titl
sqlite> 

ในขณะที่เอฟเฟกต์การแทรก / อัปเดตเหมือนเดิมการidเปลี่ยนแปลงตามประเภทคำจำกัดความของตาราง (ดูตารางที่สองที่ 'อลิซ' มีอยู่ในขณะนี้id = 4ตารางแรกทำงานได้มากกว่าที่ฉันคาดไว้ให้ทำ ) ระวังผลกระทบนี้


1

หากคุณมีตารางอยู่แล้วและไม่สามารถ / ไม่ต้องการสร้างมันขึ้นใหม่ไม่ว่าจะด้วยเหตุผลใดก็ตามให้ใช้ดัชนี :

CREATE UNIQUE INDEX my_index ON my_table(col_1, col_2);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.