web-dev-qa-db-fra.com

Métadonnées d'information de schéma SQLite

Je dois obtenir les noms des colonnes et leurs tables dans une base de données SQLite. Ce dont j'ai besoin, c'est un résultat avec 2 colonnes: table_name | column_name

En MySQL, je peux obtenir ces informations avec une requête SQL sur la base de données INFORMATION_SCHEMA. Cependant, SQLite propose la table sqlite_master

sqlite> create table students (id INTEGER, name TEXT);
sqlite> select * from sqlite_master;
  table|students|students|2|CREATE TABLE students (id INTEGER, name TEXT)

il en résulte une requête de construction DDL (CREATE TABLE) qui ne m’aide en rien et j’ai besoin de l’analyser pour obtenir des informations pertinentes. 

Je dois obtenir une liste de tables et les joindre avec des colonnes ou simplement obtenir des colonnes avec une colonne de nom de table. Donc, PRAGMA table_info(TABLENAME) ne fonctionne pas pour moi car je n'ai pas le nom de la table. Je veux obtenir toutes les métadonnées de colonne dans la base de données.

Existe-t-il un meilleur moyen d'obtenir ces informations en tant que résultat en interrogeant la base de données?

36
AhmetB - Google

Vous avez essentiellement nommé la solution dans votre question.

Pour obtenir une liste des tables (et des vues), interrogez sqlite_master comme dans 

SELECT name, sql FROM sqlite_master
WHERE type='table'
ORDER BY name;

(voir le SQLite FAQ )

Pour obtenir des informations sur les colonnes d'une table spécifique, utilisez PRAGMA table_info(table-name); comme expliqué dans la documentation SQLite PRAGMA .

Je ne connais aucun moyen d'obtenir un nom_table | nom_colonne renvoyé à la suite d'une seule requête. Je ne crois pas que SQLite supporte cela. La meilleure solution consiste probablement à utiliser les deux méthodes ensemble pour renvoyer les informations recherchées. Commencez par obtenir la liste des tables à l'aide de sqlite_master, puis parcourez-les pour obtenir leurs colonnes à l'aide de PRAGMA table_info ().

72
Tom Juergens

Il existe des commandes ".tables" et ".schema [nom_table]" qui donnent en quelque sorte une version séparée au résultat obtenu avec "select * from sqlite_master;"

Il y a aussi "pragma table_info ([table_name]);" commande pour obtenir un meilleur résultat pour l'analyse au lieu d'une requête de construction:


sqlite> .tables
students
sqlite> .schema students
create table students(id INTEGER, name TEXT);
sqlite> pragma table_info(students);
0|id|INTEGER|0||0
1|name|TEXT|0||0

J'espère que ça aide dans une certaine mesure ...

9
Mustafa Zengin

Pour votre information, si vous utilisez .Net, vous pouvez utiliser la méthode DbConnection.GetSchema pour récupérer des informations qui se trouvent généralement dans INFORMATION_SCHEMA. Si vous avez une couche d'abstraction, vous pouvez avoir le même code pour tous les types de bases de données (notez que MySQL semble remplacer les 2 premiers arguments du tableau de restrictions).

4
user276648

Une autre astuce utile consiste à obtenir d’abord tous les noms de tables auprès de sqlite_master.

Ensuite, pour chacun d'eux, lancez une requête "select * from t où 1 = 0". Si vous analysez la structure de la requête résultante - cela dépend de la langue/de l'API à partir de laquelle vous l'appelez - vous obtenez une structure riche décrivant les colonnes.

En python

c = ...db.cursor()
c.execute("select * from t where 1=0");
c.fetchall();
print c.description;

Juraj

PS. J'ai l'habitude d'utiliser 'où 1 = 0' car la syntaxe de limitation des enregistrements semble varier d'une base à l'autre. De plus, une bonne base de données optimisera cette clause toujours fausse.

Le même effet, en SQLite, est obtenu avec la «limite 0». 

4
Juraj

Essayez cet analyseur de schéma de table sqlite, j’ai implémenté l’analyseur de table sqlite pour analyser les définitions de table en PHP.

Il renvoie les définitions complètes (unique, clé primaire, type, précision, non nul, références, contraintes de table, etc.)

https://github.com/maghead/sqlite-parser

La syntaxe est la suivante: syntaxe de l'instruction sqlite create table: http://www.sqlite.org/lang_createtable.html

2
c9s

Les versions récentes de SQLite vous permettent de sélectionner les résultats PRAGMA maintenant , ce qui facilite cette opération:

SELECT 
  m.name as table_name, 
  p.name as column_name
FROM 
  sqlite_master AS m
JOIN 
  pragma_table_info(m.name) AS p
ORDER BY 
  m.name, 
  p.cid

p.cid contient l'ordre des colonnes de l'instruction CREATE TABLE, indexée à zéro.

David Garoutte a répondu ceci ici , mais ce code SQL devrait s'exécuter plus rapidement et les colonnes sont classées par le schéma, et non par ordre alphabétique.

Notez que table_info contient également 

  • type (le type de données, comme integer ou text), 
  • notnull (1 si la colonne a une contrainte NOT NULL)
  • dflt_value (NULL si aucune valeur par défaut)
  • pk (1 si la colonne est la clé primaire de la table, sinon 0)

RTFM: https://www.sqlite.org/pragma.html#pragma_table_info

2
mrm

C'est une vieille question, mais à cause du nombre de fois qu'il a été vu, nous ajoutons à la question pour la simple raison que la plupart des réponses vous expliquent comment trouver les noms TABLE dans la base de données SQLite QUE FAITES-VOUS QUAND LE NOM DE LA TABLE IS N'EST PAS DANS LA BASE DE DONNEES? Cela arrive à notre application parce que nous créons des TABLES par programme. Profitez de la base de données

    public void toPageTwo(View view){

    if(etQuizTable.getText().toString().equals("")){
        Toast.makeText(getApplicationContext(), "Enter Table Name\n\n"
                +"           OR"+"\n\nMake Table First", Toast.LENGTH_LONG 
   ).show();
        etQuizTable.requestFocus();
        return;
    }

    NEW_TABLE = etQuizTable.getText().toString().trim();
    db = dbHelper.getWritableDatabase();
    ArrayList<String> arrTblNames = new ArrayList<>();
    Cursor c = db.rawQuery("SELECT name FROM sqlite_master WHERE 
   type='table'", null);

    if (c.moveToFirst()) {
        while ( !c.isAfterLast() ) {
            arrTblNames.add( c.getString( c.getColumnIndex("name")) );
            c.moveToNext();
        }
    }
    c.close();
    db.close();

    boolean matchFound = false;
    for(int i=0;i<arrTblNames.size();i++) {
        if(arrTblNames.get(i).equals(NEW_TABLE)) {
            Intent intent = new Intent(ManageTables.this, TableCreate.class 
   );
            startActivity( intent );
            matchFound = true;
        }
    }
    if (!matchFound) {
        Toast.makeText(getApplicationContext(), "No Such Table\n\n"
                +"           OR"+"\n\nMake Table First", Toast.LENGTH_LONG 
 ).show();
        etQuizTable.requestFocus();
    }
}
0
James_Duh