56 votes

Quel nom de colonne SQLite peut être/ne peut pas être?

Y a-t-il une règle pour le nom de colonne de SQLite?

  • Peut-il contenir des caractères comme '/'?
  • Peut-il être en UTF-8?

21voto

J. Polfer Points 5895

Est-ce que cela peut avoir des caractères comme '/'?

Tous les exemples proviennent de SQLite 3.5.9 fonctionnant sur Linux.

Si vous entourez le nom de la colonne de guillemets doubles, vous pouvez :

> CREATE TABLE test_forward ( /test_column INTEGER );
Erreur SQL: près de "/": erreur de syntaxe
> CREATE TABLE test_forward ("/test_column" INTEGER );
> INSERT INTO test_forward("/test_column") VALUES (1);
> SELECT test_forward."/test_column" from test_forward;
1

Cela dit, vous ne devriez probablement pas faire cela.

3 votes

Vous pouvez le faire, mais cela sera une galère pour le reste de la vie de la base de données. Je recommande fortement de ne pas le faire.

0 votes

@Brian Hooper - Je suis d'accord, mais en fait ça semble être une bonne pratique d'ajouter des guillemets simples/doubles après avoir lu sqlite.org/lang_keywords.html. Je vois rarement ça dans les requêtes du monde réel, cependant.

0 votes

Je préfère éviter d'utiliser des mots réservés comme noms de table et de colonne. Cela peut poser des problèmes lors de la migration et d'activités similaires, mais le nombre de mots réservés n'est pas vraiment très grand et ils peuvent être évités avec un peu de réflexion. Je préfère cela à devoir m'inquiéter de ces petits détails pour le reste de mon emploi. Mais certains générateurs de code les fournissent automatiquement, donc ce n'est peut-être pas un problème si vous en utilisez un.

13voto

user35443 Points 2031

La réponse suivante est basée sur le code source de SQLite, en se basant principalement sur le fichier parse.y (entrée pour le parseur lemon).

TL;DR :

Les séries de caractères autorisées pour les noms de colonnes et de tables dans les instructions CREATE TABLE sont

  • Chaines échappées en ' de n'importe quel type (même des mots-clés)
  • Identificateurs, ce qui signifie
    • Chaines échappées en ``` et " de n'importe quel type (même des mots-clés)
    • une série de caractères ASCII 8 bits ou de caractères ASCII 7 bits avec le 1 dans le tableau suivant qui ne forme pas un mot-clé : Caractères d'identificateurs valides
  • Mot-clé INDEXED car c'est non-standard
  • Mot-clé JOIN pour une raison inconnue pour moi.

Les séries de caractères autorisées pour les colonnes de résultat dans une instruction SELECT sont

  • Soit une chaine soit un identifiant comme décrit ci-dessus
  • Tout ce qui précède si utilisé comme alias de colonne écrit après AS

Maintenant à l'exploration du processus en lui-même

  1. examinons la syntaxe pour les colonnes de CREATE TABLE

    // Le nom d'une colonne ou d'une table peut être l'un des suivants :
    //
    %type nm {Token}
    nm(A) ::= id(X).         {A = X;}
    nm(A) ::= STRING(X).     {A = X;}
    nm(A) ::= JOIN_KW(X).    {A = X;}
  2. Allons plus en profondeur, nous découvrons que

    // Un IDENTIFICATEUR peut être un identificateur générique, ou l'un de plusieurs
    // mots-clés. Tout mot-clé non-standard peut également être un identificateur.
    //
    %type id {Token}
    id(A) ::= ID(X).         {A = X;}
    id(A) ::= INDEXED(X).    {A = X;}

    "Identificateur générique" semble inconnu. Un rapide coup d'œil dans tokenize.c cependant apporte la définition

    /*
    ** La fonction sqlite3KeywordCode vérifie un identificateur pour déterminer s'il
    ** s'agit d'un mot-clé. Si c'est un mot-clé, le code de jeton de ce mot-clé est
    ** retourné. Si l'entrée n'est pas un mot-clé, TK_ID est retourné.
    */
    
    /*
    ** Si X est un caractère pouvant être utilisé dans un identificateur alors
    ** IdChar(X) sera vrai. Sinon, il est faux.
    **
    ** Pour l'ASCII, tout caractère avec le bit d'ordre élevé défini est
    ** autorisé dans un identificateur. Pour les caractères 7 bits,
    ** sqlite3IsIdChar[X] doit être 1.
    **
    ** Ticket #1066. la norme SQL n'autorise pas '$' au
    ** milieu des identificateurs. Mais de nombreuses implémentations SQL le font.
    ** SQLite autorisera '$' dans les identificateurs par compatibilité.
    ** Mais la fonctionnalité n'est pas documentée.
    */

    Pour une carte complète des caractères d'identificateurs, veuillez consulter tokenize.c.

  3. Il n'est pas encore clair quels sont les noms disponibles pour une result-column (c'est-à-dire le nom de colonne ou alias attribué dans l'instruction SELECT). parse.y est à nouveau utile ici.

    // Une phrase "AS " qui peut suivre l'une des expressions qui
    // définissent l'ensemble de résultats, ou l'une des tables dans la clause FROM.
    //
    %type as {Token}
    as(X) ::= AS nm(Y).    {X = Y;}
    as(X) ::= ids(Y).      {X = Y;}
    as(X) ::= .            {X.n = 0;}

4voto

Klaas-Z4us-V Points 91

À l'exception de placer des noms d'identifiants "illégaux" entre guillemets doubles "identifiant#1", [ avant et ] après fonctionne également [identifire#2].

Exemple:

sqlite> create table a0.tt ([id#1] integer primary key, [id#2] text) without rowid;
sqlite> insert into tt values (1,'test for [x] id''s');
sqlite> select * from tt
   ...> ;
id#1|id#2
1|test for [x] id's

2voto

Ce n'est pas une réponse complète mais cela peut aider - ce sont les mots-clés de https://www.sqlite.org/lang_keywords.html convertis en un tableau.

["ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ALWAYS", "ANALYZE", "AND", "AS", 
"ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY", "CASCADE", "CASE", "CAST", 
"CHECK", "COLLATE", "COLUMN", "COMMIT", "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT", "CURRENT_DATE", 
"CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE", "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", 
"DO", "DROP", "EACH", "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUDE", "EXCLUSIVE", "EXISTS", 
"EXPLAIN", "FAIL", "FILTER", "FIRST", "FOLLOWING", "FOR", "FOREIGN", "FROM", "FULL", "GENERATED", 
"GLOB", "GROUP", "GROUPS", "HAVING", "IF", "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", 
"INITIALLY", "INNER", "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY", 
"LAST", "LEFT", "LIKE", "LIMIT", "MATCH", "MATERIALIZED", "NATURAL", "NO", "NOT", "NOTHING", 
"NOTNULL", "NULL", "NULLS", "OF", "OFFSET", "ON", "OR", "ORDER", "OTHERS", "OUTER", 
"OVER", "PARTITION", "PLAN", "PRAGMA", "PRECEDING", "PRIMARY", "QUERY", "RAISE", "RANGE", "RECURSIVE", 
"REFERENCES", "REGEXP", "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RETURNING", "RIGHT", "ROLLBACK", 
"ROW", "ROWS", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP", "TEMPORARY", "THEN", "TIES", 
"TO", "TRANSACTION", "TRIGGER", "UNBOUNDED", "UNION", "UNIQUE", "UPDATE", "USING", "VACUUM", "VALUES", 
"VIEW", "VIRTUAL", "WHEN", "WHERE", "WINDOW", "WITH", "WITHOUT"]

0voto

collectordave Points 53

Noms de champs valides sont soumis aux mêmes règles que les noms de tables valides. Vérifiez cela avec l'administrateur de SQLite.

  1. Seuls les caractères alphanumériques et le souligné sont autorisés
  2. Le nom du champ doit commencer par un caractère alpha ou un souligné

Respectez ces règles et aucun échappement n'est nécessaire, ce qui peut éviter des problèmes à l'avenir.

13 votes

-1; La réponse de J Polfer sur cette même page démontre clairement que votre affirmation selon laquelle "Seuls les caractères alphanumériques et le souligné sont autorisés" n'est pas correcte. De plus, "Vérifié cela avec l'administrateur SQlite" n'est pas exactement une source d'information fiable.

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