189 votes

Contrainte de table SQLite - unique sur plusieurs colonnes

Je trouve des "tableaux" de syntaxe à ce sujet sur le site Web de SQLite, mais aucun exemple et mon code se bloque. J'ai d'autres tables avec des contraintes uniques sur une seule colonne, mais je veux ajouter une contrainte à la table sur deux colonnes. Voici ce que j'ai et qui provoque une SQLiteException avec le message "syntax error".

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

Je fais cela sur la base de ce qui suit :

contrainte de table

Pour être clair, la documentation sur le lien que j'ai fourni dit que CONTSTRAINT name doit passer avant la définition de ma contrainte.

Une chose qui pourrait mener à la solution est que ce qui suit mes définitions de colonnes entre parenthèses est ce dont le débogueur se plaint.

Si je mets

...last_column_name last_col_datatype) CONSTRAINT ...

l'erreur est near "CONSTRAINT" : erreur de syntaxe

Si je mets

...last_column_name last_col_datatype) UNIQUE ...

l'erreur est near "UNIQUE" : erreur de syntaxe

1 votes

Il manque une virgule à UNIQUE avant de commencer

363voto

Ayman Hourieh Points 39435

Placez la déclaration UNIQUE dans la section de définition de la colonne ; exemple de travail :

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

6 votes

Belle réponse +1. Cette syntaxe de création me permet-elle d'utiliser la méthode d'insertion normale, et non la méthode insertWithOnConflict avec le drapeau SQLiteDatabase.CONFLICT_REPLACE ?

4 votes

J'utilise ON CONFLICT IGNORE (je n'ai pas encore essayé de remplacer) avec plus de 2 colonnes, mais je ne vois pas qu'il respecte la contrainte d'unicité, il se contente d'ajouter joyeusement les doublons.

5 votes

Apparemment parce que j'ai des colonnes NULL, et que cela jette le contrôle unique par la fenêtre.

10voto

Larry Lustig Points 28706

Eh bien, votre syntaxe ne correspond pas au lien que vous avez inclus, qui spécifie :

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

0 votes

J'ai d'abord fait ça... ça n'a pas marché. J'ai réessayé juste au cas où... ça ne marche toujours pas.

9voto

Oleg Yablokov Points 199

Si vous avez déjà une table et que vous ne pouvez pas/ne voulez pas la recréer pour une raison quelconque, utilisez indices :

CREATE UNIQUE INDEX my_index ON my_table(col_1, col_2);

1voto

punkish Points 1517

Faites attention à la façon dont vous définissez la table car vous obtiendrez des résultats différents lors de l'insertion. Considérez ce qui suit

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> 

Bien que l'effet d'insertion/de mise à jour soit le même, l'effet d'insertion/de mise à jour est le même. id change en fonction du type de définition de la table (voir la deuxième table où "Alice" a maintenant id = 4 ; la première table fait davantage ce que j'attends d'elle, gardez la même PRIMARY KEY). Soyez conscient de cet effet.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X