如何转储某些SQLite3表的数据?

pup*_*eno 176 sql sqlite

如何转储数据,只转储数据库的某些SQLite3表(不是所有表)的数据,而不是模式?转储应该是SQL格式的,因为它应该稍后可以很容易地重新输入到数据库中,并且应该从命令行完成.就像是

sqlite3 db .dump
Run Code Online (Sandbox Code Playgroud)

但是没有转储模式并选择要转储的表.

Cyb*_*nic 210

你没有说你想对转储文件做什么.

我会使用以下内容来获取CSV文件,我可以将其导入几乎所有内容

.mode csv 
-- use '.separator SOME_STRING' for something other than a comma.
.headers on 
.out file.csv 
select * from MyTable;
Run Code Online (Sandbox Code Playgroud)

如果要重新插入另一个SQLite数据库,则:

.mode insert <target_table_name>
.out file.sql 
select * from MyTable;
Run Code Online (Sandbox Code Playgroud)

  • 您可以将语句放在一个文件中(例如sample.txt),然后使用以下命令调用它:sqlite3 db.sq3 <sample.txt (4认同)

jel*_*ish 147

你可以通过.schema和.dump命令来区分它们.例如用grep:

sqlite3 some.db .schema > schema.sql
sqlite3 some.db .dump > dump.sql
grep -vx -f schema.sql dump.sql > data.sql
Run Code Online (Sandbox Code Playgroud)

data.sql 文件将只包含没有架构的数据,如下所示:

BEGIN TRANSACTION;
INSERT INTO "table1" VALUES ...;
...
INSERT INTO "table2" VALUES ...;
...
COMMIT;
Run Code Online (Sandbox Code Playgroud)

我希望这可以帮助你.

  • @anurageldorado它是普通的sql.只需运行`sqlite3 some.db <data.sql` (4认同)
  • 这似乎是一个很好的解决方案,但在我的情况下,大多数线路实际上都被grep删除了..schema命令在多行上生成每个表的模式,因此有一行只包含`);`,并且grep删除包含`)的所有行;`为grep添加`-x`选项解决了这个问题问题. (2认同)

pol*_*lot 38

不是最好的方法,但至少不需要外部工具(除了grep,无论如何都是*nix盒子上的标准)

sqlite3 database.db3 .dump | grep '^INSERT INTO "tablename"'
Run Code Online (Sandbox Code Playgroud)

但是你确实需要为你正在寻找的每个表执行此命令.

请注意,这不包括架构.

  • 如果这些插入在值中有换行符,则会中断.如其他答案中的建议,更好地使用`grep -v'^ CREATE' (3认同)
  • 我使用了“sqlite3 Database.s3db .dump” (2认同)
  • 使用 `grep -v '^CREATE;` 会中断,如果 `CREATE` 语句中有换行符(有时会这样做)。最好的,IMO,根本不是自动删除 `CREATE` 语句,而是手动编辑它们。只需使用您需要的任何文本编辑器,然后搜索 `CREATE` 并手动删除这些语句。只要数据库不是很大(并且由于您使用的是sqlite,我想这是注意事项),那么这很简单。 (2认同)

Pau*_*gan 34

您可以为.dump特殊命令指定一个或多个表参数,例如sqlite3 db ".dump 'table1' 'table2'".

  • 当我按照您提到的方式添加多个表名时,它给出以下输出:用法:.dump?-preserve-rowids??喜欢吗? (2认同)

ret*_*ile 10

任何建议使用grep排除CREATE行或只是INSERTsqlite3 $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
Run Code Online (Sandbox Code Playgroud)

测试了sqlite3版本3.6.20.

如果要排除某些表,可以使用它们进行过滤$(sqlite $DB .tables | grep -v -e one -e two -e three),或者如果要获取特定的子集,请将其替换为one two three.


Dre*_*rew 8

作为对Paul Egan的回答的改进,这可以通过以下方式实现:

sqlite3 database.db3 '.dump "table1" "table2"' | grep '^INSERT'
Run Code Online (Sandbox Code Playgroud)

- 要么 -

sqlite3 database.db3 '.dump "table1" "table2"' | grep -v '^CREATE'
Run Code Online (Sandbox Code Playgroud)

当然,需要注意的是你必须安装grep.

  • 当我按照您提到的方式添加多个表名时,它会给出以下输出:Usage: .dump ?--preserve-rowids? ?类似模式? (3认同)
  • @trisweb,当然你的意思是`grep'^ INSERT'<database.sql> database_inserts.sql`,`cat`是多余的 (2认同)

Dav*_*jad 6

在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
Run Code Online (Sandbox Code Playgroud)

如果您有'面板数据,换句话说,许多具有id的单个条目将其添加到with with look并且它还会转储摘要统计信息:

        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 
Run Code Online (Sandbox Code Playgroud)


Fra*_*uga 5

审查其他可能的解决方案

仅包含 INSERT

sqlite3 database.db3 .dump | grep '^INSERT INTO "tablename"'
Run Code Online (Sandbox Code Playgroud)

易于实施,但如果您的任何列包含新行,它将失败

SQLite 插入模式

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

这是一个很好且可定制的解决方案,但如果您的列在空间中具有像“几何”类型的 blob 对象,则它不起作用

使用模式区分转储

sqlite3 some.db .schema > schema.sql
sqlite3 some.db .dump > dump.sql
grep -v -f schema.sql dump > data.sql
Run Code Online (Sandbox Code Playgroud)

不知道为什么,但对我不起作用

另一个(新的)可能的解决方案

这个问题可能没有最好的答案,但对我有用的是 grep 插入,考虑到列值中的新行,带有这样的表达式

grep -Pzo "(?s)^INSERT.*\);[ \t]*$"
Run Code Online (Sandbox Code Playgroud)

选择表确实被转储.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
Run Code Online (Sandbox Code Playgroud)

或者,更详细地尊重外键并将所有转储封装在一个事务中

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
Run Code Online (Sandbox Code Playgroud)

考虑到如果);任何列中存在字符串,grep 表达式将失败

恢复它(在已经创建表的数据库中)

sqlite3 -bail database.db3 < /tmp/backup.sql
Run Code Online (Sandbox Code Playgroud)


Pet*_*rCo 5

根据 SQLite Command Line Shell For SQLite的 SQLite 文档,您可以将 SQLite 表(或表的一部分)导出为 CSV,只需将“模式”设置为“csv”,然后运行查询以提取所需的行桌子:

sqlite> .header on
sqlite> .mode csv
sqlite> .once c:/work/dataout.csv
sqlite> SELECT * FROM tab1;
sqlite> .exit
Run Code Online (Sandbox Code Playgroud)

然后使用“.import”命令将 CSV(逗号分隔值)数据导入到 SQLite 表中:

sqlite> .mode csv
sqlite> .import C:/work/dataout.csv tab1
sqlite> .exit
Run Code Online (Sandbox Code Playgroud)

请阅读有关要考虑的两种情况的进一步文档:(1) 表“tab1”以前不存在,(2) 表“tab1”已经存在。


小智 -3

您可以对表进行选择,在每个字段后插入逗号以生成 csv,或者使用 GUI 工具返回所有数据并将其保存到 csv。

  • 我的目的是生成一个可以轻松重新添加到数据库的 SQL 文件。 (2认同)