Как вывести данные некоторых таблиц SQLite3? - PullRequest
168 голосов
/ 16 сентября 2008

Как мне вывести данные, и только данные, а не схему, некоторых таблиц SQLite3 базы данных (не всех таблиц)? Дамп должен быть в формате SQL, так как он должен быть легко повторно введен в базу данных позже и должен быть выполнен из командной строки. Что-то вроде

sqlite3 db .dump

но без выгрузки схемы и выбора таблиц для выгрузки.

Ответы [ 13 ]

205 голосов
/ 14 октября 2008

Вы не говорите, что хотите сделать с сохраненным файлом.

Я бы использовал следующее, чтобы получить файл CSV, который я могу импортировать почти во все

.mode csv 
-- use '.separator SOME_STRING' for something other than a comma.
.headers on 
.out file.csv 
select * from MyTable;

Если вы хотите переустановить в другую базу данных SQLite, то:

.mode insert <target_table_name>
.out file.sql 
select * from MyTable;
143 голосов
/ 23 сентября 2011

Вы можете сделать это, получая разницу команд .schema и .dump. например с помощью grep:

sqlite3 some.db .schema > schema.sql
sqlite3 some.db .dump > dump.sql
grep -vx -f schema.sql dump.sql > data.sql

data.sql файл будет содержать только данные без схемы, что-то вроде этого:

BEGIN TRANSACTION;
INSERT INTO "table1" VALUES ...;
...
INSERT INTO "table2" VALUES ...;
...
COMMIT;

Надеюсь, это вам поможет.

37 голосов
/ 08 января 2009

Не лучший способ, но при аренде не нужны внешние инструменты (кроме grep, который в любом случае стандартен для * nix-боксов)

sqlite3 database.db3 .dump | grep '^INSERT INTO "tablename"'

но вам нужно выполнить эту команду для каждой таблицы, которую вы ищете.

Обратите внимание, что это не относится к схеме.

34 голосов
/ 21 декабря 2009

Для специальной команды .dump можно указать один или несколько аргументов таблицы, например, sqlite3 db ".dump 'table1' 'table2'".

10 голосов
/ 16 ноября 2013

Любой ответ, который предлагает использовать grep для исключения строк CREATE или просто получить строки INSERT из вывода sqlite3 $DB .dump, потерпит неудачу. Команды CREATE TABLE отображают один столбец на строку (поэтому исключая CREATE, вы не получите все это), а значения в строках INSERT могут иметь встроенные символы новой строки (поэтому вы не можете получить только строки INSERT ).

for t in $(sqlite3 $DB .tables); do
    echo -e ".mode insert $t\nselect * from $t;"
done | sqlite3 $DB > backup.sql

Протестировано на sqlite3 версии 3.6.20.

Если вы хотите исключить определенные таблицы, вы можете отфильтровать их с помощью $(sqlite $DB .tables | grep -v -e one -e two -e three), или если вы хотите получить определенное подмножество, замените его на one two three.

8 голосов
/ 02 ноября 2011

Как улучшение ответа Пола Игана, это можно сделать следующим образом:

sqlite3 database.db3 '.dump "table1" "table2"' | grep '^INSERT'

- или -

sqlite3 database.db3 '.dump "table1" "table2"' | grep -v '^CREATE'

Предостережение, конечно, в том, что вам нужно установить grep.

6 голосов
/ 14 мая 2014

В Python, Java или любом другом языке высокого уровня .dump не работает. Нам нужно закодировать преобразование в CSV вручную. Я привожу пример с Python. Другие, примеры будут оценены:

from os import path   
import csv 

def convert_to_csv(directory, db_name):
    conn = sqlite3.connect(path.join(directory, db_name + '.db'))
    cursor = conn.cursor()
    cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
    tables = cursor.fetchall()
    for table in tables:
        table = table[0]
        cursor.execute('SELECT * FROM ' + table)
        column_names = [column_name[0] for column_name in cursor.description]
        with open(path.join(directory, table + '.csv'), 'w') as csv_file:
            csv_writer = csv.writer(csv_file)
            csv_writer.writerow(column_names)
            while True:
                try:
                    csv_writer.writerow(cursor.fetchone())
                except csv.Error:
                    break

Если у вас есть данные панели, другими словами, многие отдельные записи с идентификаторами добавляют это к внешнему виду, а также выводит сводную статистику:

        if 'id' in column_names:
            with open(path.join(directory, table + '_aggregate.csv'), 'w') as csv_file:
                csv_writer = csv.writer(csv_file)
                column_names.remove('id')
                column_names.remove('round')
                sum_string = ','.join('sum(%s)' % item for item in column_names)
                cursor.execute('SELECT round, ' + sum_string +' FROM ' + table + ' GROUP BY round;')
                csv_writer.writerow(['round'] + column_names)
                while True:
                    try:
                        csv_writer.writerow(cursor.fetchone())
                    except csv.Error:
                        break 
4 голосов
/ 19 января 2017

В соответствии с документацией SQLite для командной строки Для SQLite вы можете экспортировать таблицу SQLite (или часть таблицы) как CSV, просто установив для «mode» значение «csv», а затем запустите запрос для извлечения нужных строк таблицы:

sqlite> .header on
sqlite> .mode csv
sqlite> .once c:/work/dataout.csv
sqlite> SELECT * FROM tab1;
sqlite> .exit

Затем используйте команду ".import" для импорта данных CSV (значения, разделенные запятыми) в таблицу SQLite:

sqlite> .mode csv
sqlite> .import C:/work/dataout.csv tab1
sqlite> .exit

Пожалуйста, прочтите дополнительную документацию о двух рассматриваемых случаях: (1) таблица «tab1» ранее не существует и (2) таблица «tab1» уже существует.

3 голосов
/ 18 мая 2016

Обзор других возможных решений

Включить только вставки

sqlite3 database.db3 .dump | grep '^INSERT INTO "tablename"'

Простота реализации, но она потерпит неудачу, если в любом из ваших столбцов появятся новые строки

Режим вставки SQLite

for t in $(sqlite3 $DB .tables); do
    echo -e ".mode insert $t\nselect * from $t;"
done | sqlite3 $DB > backup.sql

Это хорошее и настраиваемое решение, но оно не работает, если в ваших столбцах есть объекты типа BLOB-объектов типа Geometry в пространственном элементе

Развалить дамп со схемой

sqlite3 some.db .schema > schema.sql
sqlite3 some.db .dump > dump.sql
grep -v -f schema.sql dump > data.sql

Не знаю почему, но у меня не работает

Другое (новое) возможное решение

Возможно, нет лучшего ответа на этот вопрос, но тот, который мне подходит, это grep вставки, принимая во внимание, что это новые строки в значениях столбцов с выражением , подобным этому

grep -Pzo "(?s)^INSERT.*\);[ \t]*$"

Для выбора таблиц выдается дамп .dump допускает использование аргумента LIKE для совпадения с именами таблиц, но если этого недостаточно, возможно, лучше использовать простой скрипт

TABLES='table1 table2 table3'

echo '' > /tmp/backup.sql
for t in $TABLES ; do
    echo -e ".dump ${t}" | sqlite3 database.db3 | grep -Pzo "(?s)^INSERT.*?\);$" >> /tmp/backup.sql
done

или что-то более сложное, чтобы уважать внешние ключи и инкапсулировать весь дамп только в одну транзакцию

TABLES='table1 table2 table3'

echo 'BEGIN TRANSACTION;' > /tmp/backup.sql
echo '' >> /tmp/backup.sql
for t in $TABLES ; do
    echo -e ".dump ${t}" | sqlite3 $1 | grep -Pzo "(?s)^INSERT.*?\);$" | grep -v -e 'PRAGMA foreign_keys=OFF;' -e 'BEGIN TRANSACTION;' -e 'COMMIT;' >> /tmp/backup.sql
done

echo '' >> /tmp/backup.sql
echo 'COMMIT;' >> /tmp/backup.sql

Учтите, что выражение grep не будет выполнено, если ); - строка, присутствующая в любом из столбцов

Чтобы восстановить его (в базе данных с уже созданными таблицами)

sqlite3 -bail database.db3 < /tmp/backup.sql
3 голосов
/ 17 сентября 2008

Лучший способ - взять код, который будет делать дамп sqlite3 db, за исключением частей схемы.

Пример псевдокода:

SELECT 'INSERT INTO ' || tableName || ' VALUES( ' || 
  {for each value} ' quote(' || value || ')'     (+ commas until final)
|| ')' FROM 'tableName' ORDER BY rowid DESC

См .: src/shell.c:838 (для sqlite-3.5.9) для фактического кода

Вы можете даже взять эту оболочку, закомментировать части схемы и использовать ее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...