web-dev-qa-db-ja.com

SQLiteテーブル制約-複数の列で一意

これについては、SQLite Webサイトで構文「チャート」を見つけることができますが、例はなく、コードがクラッシュします。単一の列に一意の制約を持つ他のテーブルがありますが、2つの列のテーブルに制約を追加したいです。これは、メッセージ「構文エラー」でSQLiteExceptionを引き起こしているものです。

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

私はこれに基づいてこれをやっています:

table-constraint

明確にするために、私が提供したリンクのドキュメントには、CONTSTRAINT nameが制約定義の前に来る必要があると書かれています。

しかし、ソリューションにつながる可能性のあるものは、括弧で囲まれた列定義に続くものがデバッガーから不満を持っていることです。

入れたら

...last_column_name last_col_datatype) CONSTRAINT ...

エラーは「CONSTRAINT」付近:構文エラー

入れたら

...last_column_name last_col_datatype) UNIQUE ...

エラーは「UNIQUE」の近く:構文エラー

170
Rich

列定義セクション内にUNIQUE宣言を配置します。

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

作業例:

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

さて、あなたの構文はあなたが含めたリンクと一致しません。

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

挿入時に異なる結果が得られるように、テーブルの定義方法に注意してください。以下を考慮してください



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はテーブル定義タイプに基づいて変化します(「Alice」にid = 4が追加された2番目のテーブルを参照してください。最初のテーブルは期待以上のことをしていますそれを行うには、プライマリキーを同じに保ちます)。この影響に注意してください。

0
punkish