it-swarm.com.de

Finden Sie SQLite-Spaltennamen in leerer Tabelle

Für Tricks schreibe ich ein "Schemadokumentations-Tool", das eine Beschreibung der Tabellen und Beziehungen in einer Datenbank generiert. Ich bin gerade dabei, mit SQLite zusammenzuarbeiten.

Es ist mir gelungen, die Namen aller Tabellen in einer SQLite-Datenbank über eine Abfrage in der Tabelle sqlite_master zu extrahieren. Für jeden Tabellennamen feuere ich dann einen einfachen ab

select * from <table name>

abfrage, dann verwenden Sie die APIs sqlite3_column_count() und sqlite3_column_name(), um die Spaltennamen zu sammeln, die ich weiter an sqlite3_table_column_metadata() weiterführe, um zusätzliche Informationen zu erhalten. Einfach genug, richtig?

Das Problem ist, dass es nur für Tabellen funktioniert, die nicht leer sind. Das heißt, die sqlite_column_*()-APIs sind nur gültig, wenn sqlite_step()SQLITE_ROW zurückgegeben hat, was bei leeren Tabellen nicht der Fall ist.

Die Frage ist also, wie kann ich Spaltennamen für leere Tabellen finden? Oder gibt es generell einen besseren Weg, um diese Art von Schemainformationen in SQLite abzurufen?

Ich habe das Gefühl, dass irgendwo ein weiterer versteckter sqlite_xxx-Tisch lauern muss, der diese Informationen enthält, aber bisher nicht gefunden wurde. 

36
Drew Hall
sqlite> .header on
sqlite> .mode column
sqlite> create table ABC(A TEXT, B VARCHAR);
sqlite> pragma table_info(ABC);
cid         name        type        notnull     dflt_value  pk
----------  ----------  ----------  ----------  ----------  ----------
0           A           TEXT        0                       0
1           B           VARCHAR     0                       0
62
pragmanatu

Führen Sie die Abfrage aus:

PRAGMA table_info( your_table_name );

Dokumentation

10

PRAGMA table_info( your_table_name ); funktioniert nicht in HTML5-SQLite.

Hier ist ein kleines HTML5-SQLite-JavaScript-Snippet, das die Spaltennamen von your_table_name erhält, auch wenn diese leer sind. Hoffe es ist hilfreich.

tx.executeSql('SELECT name, sql FROM sqlite_master WHERE type="table" AND name = "your_table_name";', [], function (tx, results) {
  var columnParts = results.rows.item(0).sql.replace(/^[^\(]+\(([^\)]+)\)/g, '$1').split(',');
  var columnNames = [];
  for(i in columnParts) {
    if(typeof columnParts[i] === 'string')
      columnNames.Push(columnParts[i].split(" ")[0]);
  }
  console.log(columnNames);
  ///// Your code which uses the columnNames;
});
4
GeekTantra

Führen Sie diese Abfrage aus 

select * from (select "") left join my_table_to_test b on -1 = b.rowid;

Sie können es bei online sqlite engine ausprobieren

4
user941581

Die von @pragmanatu vorgeschlagene Anweisung PRAGMA funktioniert auch über jede programmatische Schnittstelle. Alternativ hat die sql -Spalte von sqlite_master die SQL-Anweisung CREATE TABLE &c &c, die die Tabelle beschreibt (aber Sie müssten das analysieren, also denke ich, PRAGMA table_info ist ... pragmatischer;.

3
Alex Martelli

Wenn Sie SQLite 3.8.3 oder höher verklagen (unterstützt die WITH-Klausel), sollte diese rekursive Abfrage für Basistabellen funktionieren. Zu CTAS, YMMV.

WITH
    Recordify(tbl_name, Ordinal, Clause, Sql)
AS
    (
     SELECT
        tbl_name,
        0,

        '',
        Sql
     FROM
        (
         SELECT
            tbl_name,
            substr
            (
             Sql,
             instr(Sql, '(') + 1,
             length(Sql) - instr(Sql, '(') - 1
            ) || ',' Sql
         FROM
            sqlite_master
         WHERE
            type = 'table'
        )
     UNION ALL
     SELECT
        tbl_name,
        Ordinal + 1,
        trim(substr(Sql, 1, instr(Sql, ',') - 1)),
        substr(Sql, instr(Sql, ',') + 1)
     FROM
        Recordify
     WHERE
        Sql > ''
       AND  lower(trim(Sql)) NOT LIKE 'check%'
       AND  lower(trim(Sql)) NOT LIKE 'unique%'
       AND  lower(trim(Sql)) NOT LIKE 'primary%'
       AND  lower(trim(Sql)) NOT LIKE 'foreign%'
       AND  lower(trim(Sql)) NOT LIKE 'constraint%'
    ),
    -- Added to make querying a subset easier.
    Listing(tbl_name, Ordinal, Name, Constraints)
AS
    (
     SELECT
        tbl_name,
        Ordinal,
        substr(Clause, 1, instr(Clause, ' ') - 1),
        trim(substr(Clause, instr(Clause, ' ') + 1))
     FROM
        Recordify
     WHERE
        Ordinal > 0
    )
SELECT
    tbl_name,
    Ordinal,
    Name,
    Constraints
FROM
    Listing
ORDER BY
    tbl_name,
    lower(Name);
0
user2812175