Найти имена столбцов SQLite в пустой таблице - PullRequest
36 голосов
/ 30 мая 2009

Для удовольствия я пишу инструмент «документация схемы», который генерирует описание таблиц и связей в базе данных. В настоящее время я использую его для работы с SQLite.

Мне удалось извлечь имена всех таблиц в базе данных SQLite с помощью запроса к таблице sqlite_master. Для каждого имени таблицы я запускаю простое

select * from <table name>

запрос, затем используйте API-интерфейсы sqlite3_column_count() и sqlite3_column_name() для сбора имен столбцов, которые я далее добавлю к sqlite3_table_column_metadata() для получения дополнительной информации. Достаточно просто, верно?

Проблема в том, что он работает только для непустых таблиц. То есть API sqlite_column_*() действительны только в том случае, если sqlite_step() вернул SQLITE_ROW, что не относится к пустым таблицам.

Итак, вопрос в том, как мне найти имена столбцов для пустых таблиц? Или, в более общем смысле, есть ли лучший способ получить информацию об этом типе схемы в SQLite?

Мне кажется, что где-то скрывается еще одна скрытая таблица sqlite_xxx, содержащая эту информацию, но до сих пор не удалось ее найти.

Ответы [ 6 ]

62 голосов
/ 30 мая 2009
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
10 голосов
/ 30 мая 2009

Выполнить запрос:

PRAGMA table_info( your_table_name );

Документация

4 голосов
/ 08 декабря 2011

PRAGMA table_info( your_table_name ); не работает в HTML5 SQLite.

Вот небольшой фрагмент HTML5 JavaScript JavaScript, который получает имена столбцов из your_table_name, даже если он пуст Надеюсь, что это полезно.

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 голосов
/ 13 сентября 2011

Выполнить этот запрос

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

Вы можете попробовать его на онлайн-движке sqlite

3 голосов
/ 30 мая 2009

Оператор PRAGMA, предложенный @pragmanatu, прекрасно работает и через любой программный интерфейс. В качестве альтернативы, в столбце sql в sqlite_master есть оператор SQL CREATE TABLE &c &c, который описывает таблицу (но вам придется ее проанализировать, поэтому я думаю, PRAGMA table_info более ... прагматично ;-) .

0 голосов
/ 19 июня 2014

Если вы используете SQLite 3.8.3 или новее (поддерживает предложение WITH), этот рекурсивный запрос должен работать для базовых таблиц. На 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...