如何转储数据库的某些 SQLite3 表(不是所有表)的数据,仅转储数据,而不转储模式?转储应该是 SQL 格式,因为它应该稍后很容易重新输入到数据库中,并且应该从命令行完成。就像是
sqlite3 db .dump
但无需转储模式并选择要转储的表。
你不是说你想对转储的文件做什么。
获取 CSV 文件(可以导入几乎所有内容)
.mode csv
-- use '.separator SOME_STRING' for something other than a comma.
.headers on
.out file.csv
select * from MyTable;
获取 SQL 文件(可以重新插入到不同的 SQLite 数据库中)
.mode insert <target_table_name>
.out file.sql
select * from MyTable;
您可以这样做以获得 .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;
我希望这可以帮助你。
您可以为 .dump 特殊命令指定一个或多个表参数,例如 .dump sqlite3 db ".dump 'table1' 'table2'"
。
不是最好的方法,但至少不需要外部工具(grep 除外,它是 *nix 盒子的标准)
sqlite3 database.db3 .dump | grep '^INSERT INTO "tablename"'
但是您确实需要为要查找的每个表执行此命令。
请注意,这不包括架构。
任何建议使用 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
。
作为对 Paul Egan 答案的改进,可以按如下方式完成:
sqlite3 database.db3 '.dump "table1" "table2"' | grep '^INSERT'
- 或者 -
sqlite3 database.db3 '.dump "table1" "table2"' | grep -v '^CREATE'
当然,需要注意的是您必须安装 grep。
在 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
如果您有'面板数据,换句话说,许多带有 id 的单个条目将其添加到 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
仅包括 INSERT
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
这是一个不错且可自定义的解决方案,但如果您的列在 spatialite 中具有像“几何”类型这样的 blob 对象,则它不起作用
将转储与架构进行比较
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
根据 SQLite命令行 Shell的 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”确实存在。
最好的方法是采用 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)
您甚至可以只使用该外壳并注释掉架构部分并使用它。
此版本适用于插入内的换行符:
sqlite3 database.sqlite3 .dump | grep -v '^CREATE'
CREATE
在实践中排除所有以不太可能包含换行符开头的行
回溯的答案应该是最接近的答案,但它不适用于我的情况。一个插入查询刚刚在中间中断,导出刚刚停止。不知道是什么原因。但是它在.dump
.
最后,我编写了一个工具来拆分生成的 SQL .dump
:
您可以对表格进行选择,在每个字段后插入逗号以生成 csv,或使用 GUI 工具返回所有数据并将其保存到 csv。