web-dev-qa-db-fra.com

Existe-t-il un moyen d'obtenir un schéma de base de données à partir de python?

J'essaie de trouver un moyen de trouver les noms des tables dans une base de données (s'il en existe). Je trouve que d'une cli sqlite je peux utiliser:

>.tables

Puis pour les champs:

>PRAGMA TABLE_INFO(table_name)

Cela ne fonctionne évidemment pas avec python. Y a-t-il même un moyen de faire cela avec python ou devrais-je simplement utiliser la ligne de commande sqlite?

19
tijko

Vous devriez pouvoir accéder aux noms de table à partir de la table sqlite_master.

SELECT name FROM sqlite_master WHERE type='table';

Les noms des colonnes ne sont pas directement accessibles. Le moyen le plus simple de les obtenir consiste à interroger la table et à obtenir les noms de colonne à partir du résultat de la requête.

SELECT * FROM table_name LIMIT 1;
21
Tom Kerr

Depuis le sqlite FAQ :

À partir d'un programme C/C++ (ou d'un script utilisant des liaisons Tcl/Ruby/Perl/Python), vous pouvez accéder aux noms de table et d'index en effectuant une SELECT sur une table spéciale nommée "SQLITE_MASTER". Chaque base de données SQLite a une table SQLITE_MASTER qui définit le schéma de la base de données. La table SQLITE_MASTER ressemble à ceci:

CREATE TABLE sqlite_master (
  type TEXT,
  name TEXT,
  tbl_name TEXT,
  rootpage INTEGER,
  sql TEXT
);

Donc, pour obtenir une liste de tous les noms de table, exécutez:

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

Pour obtenir les noms de colonne pour une table donnée, utilisez la commande pragma table_info :

Ce pragma renvoie une ligne pour chaque colonne de la table nommée. Les colonnes du jeu de résultats incluent le nom de la colonne, le type de données, si la colonne peut être NULL ou non, et la valeur par défaut de la colonne.

Cette commande fonctionne très bien à partir de python:

>>> import sqlite3
>>> conn = sqlite3.connect(':mem:')
>>> for row in conn.execute("pragma table_info('sqlite_master')").fetchall():
...     print row
... 
(0, u'type', u'text', 0, None, 0)
(1, u'name', u'text', 0, None, 0)
(2, u'tbl_name', u'text', 0, None, 0)
(3, u'rootpage', u'integer', 0, None, 0)
(4, u'sql', u'text', 0, None, 0)

Malheureusement, les instructions pragma ne fonctionnent pas avec les paramètres; vous devrez insérer manuellement le nom de la table (assurez-vous qu'elle ne provient pas d'une source non fiable et échappez-la correctement).

30
Martijn Pieters

Voici une imprimante pratique que j'ai écrite et basée sur la réponse de Martijn:

def printSchema(connection):
    for (tableName,) in connection.execute(
        """
        select NAME from SQLITE_MASTER where TYPE='table' order by NAME;
        """
    ):
        print("{}:".format(tableName))
        for (
            columnID, columnName, columnType,
            columnNotNull, columnDefault, columnPK,
        ) in connection.execute("pragma table_info('{}');".format(tableName)):
            print("  {id}: {name}({type}){null}{default}{pk}".format(
                id=columnID,
                name=columnName,
                type=columnType,
                null=" not null" if columnNotNull else "",
                default=" [{}]".format(columnDefault) if columnDefault else "",
                pk=" *{}".format(columnPK) if columnPK else "",
            ))
6

Pour obtenir les noms de champs, utilisez cur.description après la requête:

import sqlite3.dbapi2 as sqlite
con = sqlite.connect(":memory:")
cur = con.cursor()
con.executescript("""
    create table test (name, address);
    insert into test (name, address) values ("Jer", "Monterey Street");
""")

cur.execute("select * from test where 1=0")
rs = cur.fetchall()  ## will be [] because of where clause
field_names = [r[0] for r in cur.description]
2
Paul McNett

Utilisez l'objet sqlite row. Un objet de ligne a des clés () qui vous donneront le schéma.

depuis docs.python.org

conn.row_factory = sqlite3.Row
c = conn.cursor()
c.execute('select * from stocks')
  <sqlite3.Cursor object at 0x7f4e7dd8fa80>
r = c.fetchone()
type(r)
  <type 'sqlite3.Row'>
  r
  (u'2006-01-05', u'BUY', u'RHAT', 100.0, 35.14)
r.keys()
  ['date', 'trans', 'symbol', 'qty', 'price']
1
Perennial

Je viens d'essayer

SELECT name FROM my_db.sqlite_master WHERE type='table';

combiner la réponse de Tom Kerr à la tentative de récupération d'informations sur une base de données attachée. Au début ça n'a pas marché. Il s'avère que je dois d'abord attacher l'autre base de données de cette façon:

ATTACH DATABASE 'file:my_other_database_file.db?cache=shared' as my_db;

sinon, la base de données n'obtiendra pas un verrou en lecture pour le sqlite_master de la base de données attachée (et toutes les requêtes aboutiront avec zéro résultat) . Juste un indice au cas où quelqu'un d'autre tomberait sur cette partie du problème. 

1
starturtle

Pour obtenir les informations de schéma, IMHO, ci-dessous fonctionne également:

select sql from sqlite_master where type='table';
1
Vimanyu

les ensembles de résultats ont une description à partir de laquelle vous pouvez obtenir des informations. Il révèle certaines métadonnées de base telles que le nom de la colonne et le nombre de colonnes.

>>> rs = c.execute('''SELECT * FROM news WHERE 1=0''');
>>> dir(rs)
['__class__', '__delattr__', '__doc__', '__format__',  
'__getattribute__', '__hash__', '__init__', '__iter__', '__new__',  
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__',
'__str__', '__subclasshook__', 'arraysize', 'close', 'connection',
**'description'**, 'execute', 'executemany', 'executescript', 'fetchall',
'fetchmany', 'fetchone', 'lastrowid', 'next', 'row_factory',
'rowcount', 'setinputsizes', 'setoutputsize']



>>> print(rs.description)
(('id', None, None, None, None, None, None), 
('imageUrl', None, None, None, None, None, None), 
('headline', None, None, None, None, None, None), 
('who', None, None, None, None, None, None))
0
JustinDanielson