Как мне выгрузить данные некоторых таблиц SQLite3?

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

sqlite3 db .dump

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

В какой формат? Что-нибудь конкретное, или вы просто ищете удобочитаемую резервную копию? Пожалуйста уточни.

dmckee --- ex-moderator kitten 16.09.2008 22:55

Я хочу сделать дамп в формате SQL, чтобы можно было легко его восстановить. Я добавил эту информацию к основному вопросу.

pupeno 18.09.2008 11:01
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
190
2
222 007
13

Ответы 13

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

Я намеревался создать файл SQL, который можно было бы легко повторно добавить в БД.

pupeno 20.10.2008 09:39

Лучшим способом было бы взять код, который будет делать дамп 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) для фактического кода

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

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

Я бы использовал следующее, чтобы получить файл 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;

Есть ли способ сделать это программно с помощью операторов SQL? Я вижу, как это сделать с помощью интерпретатора, но что, если я захочу написать сценарий?

coleifer 10.10.2014 04:45

Вы можете поместить свои операторы в файл (например, sample.txt), а затем вызвать его, используя: sqlite3 db.sq3 <sample.txt

CyberFonic 14.10.2014 03:48

«Или используйте команду .once вместо .output, и вывод будет перенаправлен только для одной следующей команды перед возвратом в консоль. Используйте .output без аргументов, чтобы снова начать запись в стандартный вывод.» Документы SQLite

ruffin 14.03.2018 21:56

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

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

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

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

Я использовал sqlite3 Database.s3db .dump

Jader Dias 14.02.2011 21:23

Это сломается, если эти вставки содержат символы новой строки в значениях. Лучше используйте grep -v '^CREATE', как предлагается в одном из других ответов.

dequis 22.09.2014 15:37

использование grep -v '^CREATE; приведет к прерыванию, если в операторах CREATE есть разрывы строк (что иногда бывает). Лучше всего, ИМО, вообще не удалять операторы CREATE автоматически, а вручную отредактировать их. Просто используйте любой текстовый редактор, который вам нужен, найдите CREATE и вручную удалите эти операторы. Пока база данных не огромна (и, поскольку вы используете sqlite, я предполагаю, что это примечание), это довольно просто.

Dan Jones 08.10.2015 22:51

но grep создания также возьмет создание из представлений. как я могу это удалить?

Silve2611 01.02.2016 15:09

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

когда я добавляю несколько имен таблиц, как вы упомянули, это дает мне следующий результат: Использование: .dump? - preserve-rowids? ? КАК ОБРАЗЕЦ?

mwm 29.11.2017 01:48

@mwm Наблюдаю ту же проблему в sqlite3 3.31.1 (2020/01/27). журнал изменений ничего об этом не говорит. (Кстати, --preserve-rowids действительно работает, но совсем не документирован.)

ynn 21.03.2020 19:29

Вы можете сделать это, получив разницу команд .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;

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

@anurageldorado это простой sql. просто запустите sqlite3 some.db < data.sql

jellyfish 13.02.2016 11:07

Для меня некоторые расоны не работают. Мне нужно использовать вокруг. sqlite3 storage/db/jobs.s3db .schema jobs > schema.sql не работает, но echo '.schema' jobs | sqlite3 storage/db/jobs.s3db > schema.sql работает нормально

abkrim 27.04.2016 17:43

Это казалось хорошим решением, но в моем случае большинство строк удаляются с помощью grep. Команда .schema генерирует схему каждой таблицы в нескольких строках, поэтому есть строка, содержащая только );, а grep удаляет все строки, содержащие );. Добавление параметра -x в grep решает эту проблему.

Sunder 13.07.2016 10:49

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

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

--или же--

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

Предостережение, конечно, в том, что у вас должна быть установлена ​​программа grep.

Мне нравится этот. В качестве дополнительного бонуса он по-прежнему работает, если у вас есть сброшенный файл SQL, просто cat database.sql | grep '^INSERT' > database_inserts.sql (то же самое для схемы, замените на grep '^CREATE'

trisweb 04.06.2012 21:52

@trisweb, вы конечно имеете ввиду grep '^INSERT' < database.sql > database_inserts.sql, что cat лишний

Sebastian 17.07.2012 18:11

Ничего лишнего. cat практически ничего не стоит в исполнении и значительно упрощает цепочку ввода-вывода. Конечно, вы также можете написать < database.sql grep '^INSERT' ..., но явный канал намного легче читать.

rjh 15.02.2016 17:49

когда я добавляю несколько имен таблиц, как вы упомянули, это дает мне следующий результат: Использование: .dump? - preserve-rowids? ? КАК ОБРАЗЕЦ?

mwm 29.11.2017 01:48

-1: Искать строки с помощью CREATE - бесполезная идея. Почти каждое представление или триггер, особенно если оно содержит комментарии, требует более одной строки.

ceving 11.12.2017 17:26

Эта версия хорошо работает с символами новой строки внутри вставок:

sqlite3 database.sqlite3 .dump | grep -v '^CREATE'

На практике исключает все строки, начинающиеся с CREATE, которые с меньшей вероятностью будут содержать символы новой строки.

Любой ответ, предлагающий использовать 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.

В 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

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

        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 

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

Наконец, я написал инструмент для разделения SQL, сгенерированного из .dump:

https://github.com/motherapp/sqlite_sql_parser/

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

Включать только ВСТАВКИ

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 в Spaceite.

Дифференцируйте дамп со схемой

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

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

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

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

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

Согласно документации SQLite для Оболочка командной строки для SQLite, вы можете экспортировать таблицу SQLite (или часть таблицы) как CSV, просто установив «режим» на «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» уже существует.

Другие вопросы по теме