Найти имена столбцов SQLite в пустой таблице
Для ударов я пишу инструмент "документации схемы", который генерирует описание таблиц и отношений в базе данных. Я в настоящее время shimming его для работы с 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
, скрывающаяся где-то с этой информацией, но пока ее не удалось найти.
Ответы
Ответ 1
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
Ответ 2
Выполните запрос:
PRAGMA table_info( your_table_name );
Документация
Ответ 3
Выполните этот запрос
select * from (select "") left join my_table_to_test b on -1 = b.rowid;
Вы можете попробовать его на онлайн-сервере sqlite
Ответ 4
PRAGMA table_info( your_table_name );
не работает в HTML5 SQLite.
Ниже приведен небольшой фрагмент кода HTML5 SQLite JavaScript, который получает имена столбцов из вашего_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;
});
Ответ 5
Оператор PRAGMA
, предлагаемый @pragmanatu, отлично работает с любым программным интерфейсом. В качестве альтернативы столбец sql
sqlite_master
имеет оператор sql
CREATE TABLE &c &c
, который описывает таблицу (но вам придется анализировать это, поэтому я думаю, что PRAGMA table_info
больше... прагматично;-).
Ответ 6
Если вы подаете заявку на 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);