it-swarm.com.de

Gibt es eine Möglichkeit, ein Schema einer Datenbank aus Python heraus zu erhalten?

Ich versuche, einen Weg zu finden, um die Namen von Tabellen in einer Datenbank zu finden (falls vorhanden). Ich finde das von einem sqlite cli, das ich verwenden kann:

>.tables

Dann für die Felder:

>PRAGMA TABLE_INFO(table_name)

Dies funktioniert offensichtlich nicht innerhalb von Python. Gibt es sogar eine Möglichkeit, dies mit Python zu tun, oder sollte ich einfach die sqlite-Befehlszeile verwenden?

19
tijko

Sie sollten auf die Tabellennamen von der sqlite_master-Tabelle aus zugreifen können.

SELECT name FROM sqlite_master WHERE type='table';

Die Namen der Spalten sind nicht direkt zugänglich. Am einfachsten erhalten Sie sie, indem Sie die Tabelle abfragen und die Spaltennamen aus dem Abfrageergebnis abrufen.

SELECT * FROM table_name LIMIT 1;
21
Tom Kerr

Aus dem sqlite FAQ :

Innerhalb eines C/C++ - Programms (oder eines Skripts, das Tcl/Ruby/Perl/Python-Bindungen verwendet) können Sie auf Tabellen- und Indexnamen zugreifen, indem Sie eine SELECT für eine spezielle Tabelle namens "SQLITE_MASTER" ausführen. Jede SQLite-Datenbank verfügt über eine SQLITE_MASTER-Tabelle, die das Schema für die Datenbank definiert. Die SQLITE_MASTER-Tabelle sieht folgendermaßen aus:

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

Um eine Liste aller Tabellennamen ausführen zu lassen:

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

Verwenden Sie zum Abrufen von Spaltennamen für eine bestimmte Tabelle den Befehl pragma table_info :

Dieses Pragma gibt eine Zeile für jede Spalte in der benannten Tabelle zurück. Spalten in der Ergebnismenge umfassen den Spaltennamen, den Datentyp, ob die Spalte NULL sein kann oder nicht, und den Standardwert für die Spalte.

Dieser Befehl funktioniert gut mit 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)

Leider funktionieren pragma-Anweisungen nicht mit Parametern. Sie müssen den Tabellennamen manuell einfügen (stellen Sie sicher, dass er nicht aus einer nicht vertrauenswürdigen Quelle stammt und ordnungsgemäß entkommen).

30
Martijn Pieters

Hier ist ein praktischer Drucker, den ich basierend auf Martijns Antwort geschrieben habe:

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 "",
            ))

Verwenden Sie nach der Abfrage cur.description, um die Feldnamen abzurufen:

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

Verwenden Sie das sqlite-Zeilenobjekt. Ein Zeilenobjekt verfügt über keys (), die Ihnen das Schema geben.

von 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

Ich habe es versucht

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

tom Kerrs Antwort und den Versuch, Informationen aus einer angehängten Datenbank abzurufen. Zuerst hat es nicht funktioniert. Es stellt sich heraus, dass ich zuerst die andere Datenbank auf diese Weise anfügen muss:

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

andernfalls erhält die Datenbank keine Lesesperre für den sqlite_master der angehängten Datenbank (und alle Abfragen werden mit null Ergebnissen erfolgreich ausgeführt.) Nur ein Hinweis, falls andere Personen auf diesen Teil des Problems stoßen. 

1
starturtle

Um die Schemainformationen zu erhalten, funktioniert IMHO auch unten:

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

ergebnissätze haben eine Beschreibung, aus der Sie Informationen erhalten können. Es werden einige grundlegende Metadaten wie Spaltenname und Spaltenanzahl angezeigt.

>>> 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