如果我有大量 SQLite 数据库,并且都具有相同的架构,那么将它们合并在一起以便对所有数据库执行查询的最佳方法是什么?
从 DavidM 的回答中的 Nabble 帖子 总结一下:
attach 'c:\test\b.db3' as toMerge;
BEGIN;
insert into AuditRecords select * from toMerge.AuditRecords;
COMMIT;
detach toMerge;
根据需要重复。
注意:根据迈克的评论添加了
detach toMerge;
。
虽然是一个非常古老的线程,但这仍然是当今编程需求中的一个相关问题。我将其发布在这里是因为所提供的答案都不够简洁、简单且直截了当。这是为了最终出现在该页面上的 Google 员工。 GUI 我们开始:
Ctrl + O
键盘快捷键添加所有数据库文件Copy
,然后转到已加载数据库文件列表中的目标数据库(或根据需要创建新数据库)并右键单击目标db 并单击 Paste
我惊讶地意识到,如此艰巨的任务可以使用古老的编程技巧来解决:复制和粘贴:)
这是一个简单的 python 代码,用于合并两个数据库文件或扫描目录以查找所有数据库文件并将它们全部合并在一起(只需将其他文件中的所有数据插入到找到的第一个数据库文件中)。请注意,此代码只是附加具有相同架构的数据库。
import sqlite3
import os
def merge_databases(db1, db2):
con3 = sqlite3.connect(db1)
con3.execute("ATTACH '" + db2 + "' as dba")
con3.execute("BEGIN")
for row in con3.execute("SELECT * FROM dba.sqlite_master WHERE type='table'"):
combine = "INSERT OR IGNORE INTO "+ row[1] + " SELECT * FROM dba." + row[1]
print(combine)
con3.execute(combine)
con3.commit()
con3.execute("detach database dba")
def read_files(directory):
fname = []
for root,d_names,f_names in os.walk(directory):
for f in f_names:
c_name = os.path.join(root, f)
filename, file_extension = os.path.splitext(c_name)
if (file_extension == '.sqlitedb'):
fname.append(c_name)
return fname
def batch_merge(directory):
db_files = read_files(directory)
for db_file in db_files[1:]:
merge_databases(db_files[0], db_file)
if __name__ == '__main__':
batch_merge('/directory/to/database/files')
迟到的答案,但你可以使用:
#!/usr/bin/python
import sys, sqlite3
class sqlMerge(object):
"""Basic python script to merge data of 2 !!!IDENTICAL!!!! SQL tables"""
def __init__(self, parent=None):
super(sqlMerge, self).__init__()
self.db_a = None
self.db_b = None
def loadTables(self, file_a, file_b):
self.db_a = sqlite3.connect(file_a)
self.db_b = sqlite3.connect(file_b)
cursor_a = self.db_a.cursor()
cursor_a.execute("SELECT name FROM sqlite_master WHERE type='table';")
table_counter = 0
print("SQL Tables available: \n===================================================\n")
for table_item in cursor_a.fetchall():
current_table = table_item[0]
table_counter += 1
print("-> " + current_table)
print("\n===================================================\n")
if table_counter == 1:
table_to_merge = current_table
else:
table_to_merge = input("Table to Merge: ")
return table_to_merge
def merge(self, table_name):
cursor_a = self.db_a.cursor()
cursor_b = self.db_b.cursor()
new_table_name = table_name + "_new"
try:
cursor_a.execute("CREATE TABLE IF NOT EXISTS " + new_table_name + " AS SELECT * FROM " + table_name)
for row in cursor_b.execute("SELECT * FROM " + table_name):
print(row)
cursor_a.execute("INSERT INTO " + new_table_name + " VALUES" + str(row) +";")
cursor_a.execute("DROP TABLE IF EXISTS " + table_name);
cursor_a.execute("ALTER TABLE " + new_table_name + " RENAME TO " + table_name);
self.db_a.commit()
print("\n\nMerge Successful!\n")
except sqlite3.OperationalError:
print("ERROR!: Merge Failed")
cursor_a.execute("DROP TABLE IF EXISTS " + new_table_name);
finally:
self.db_a.close()
self.db_b.close()
return
def main(self):
print("Please enter name of db file")
file_name_a = input("File Name A:")
file_name_b = input("File Name B:")
table_name = self.loadTables(file_name_a, file_name_b)
self.merge(table_name)
return
if __name__ == '__main__':
app = sqlMerge()
app.main()
如果您只需要执行一次合并操作(以创建一个新的更大的数据库),您可以创建一个脚本/程序来循环所有 sqlite 数据库,然后将数据插入到主(大)数据库中。
Bash 助手自动合并每个数据库中的所有表
这是 https://stackoverflow.com/a/68526717/895245 的简洁 Bash 版本,它循环遍历具有相同架构的给定数据库的所有表:
sqlite-merge-dbs
#!/usr/bin/env bash
set -eu
outdb="$1"
shift
indb0="$1"
shift
cp "$indb0" "$outdb"
for table in $(sqlite3 "$outdb" "SELECT name FROM sqlite_master WHERE type='table'"); do
echo "table: $table"
for db in "$@"; do
echo "db: $db"
sqlite3 "$outdb" "attach '$db' as 'db2'" "insert into \"$table\" select * from \"db2\".\"$table\""
done
done
使用示例:
sqlite-merge-dbs out.sqlite in0.sqlite in1.sqlite in2.sqlite
测试:
rm -f in0.sqlite in1.sqlite in2.sqlite
sqlite3 in0.sqlite 'create table t(i integer, j integer)'
sqlite3 in1.sqlite 'create table t(i integer, j integer)'
sqlite3 in2.sqlite 'create table t(i integer, j integer)'
sqlite3 in0.sqlite 'insert into t values (1, -1), (2, -2)'
sqlite3 in1.sqlite 'insert into t values (3, -3), (4, -4)'
sqlite3 in2.sqlite 'insert into t values (5, -5), (6, -6)'
sqlite3 in0.sqlite 'create table s(k integer, l integer)'
sqlite3 in1.sqlite 'create table s(k integer, l integer)'
sqlite3 in2.sqlite 'create table s(k integer, l integer)'
sqlite3 in0.sqlite 'insert into s values (11, -11), (12, -12)'
sqlite3 in1.sqlite 'insert into s values (13, -13), (14, -14)'
sqlite3 in2.sqlite 'insert into s values (15, -15), (16, -16)'
./sqlite-merge-dbs out.sqlite in0.sqlite in1.sqlite in2.sqlite
sqlite3 out.sqlite 'select * from t'
echo
sqlite3 out.sqlite 'select * from s'
产生输出:
1|-1
2|-2
3|-3
4|-4
5|-5
6|-6
11|-11
12|-12
13|-13
14|-14
15|-15
16|-16
如果您已到达此提要的底部,但尚未找到解决方案,这里还有一种合并 2 个或更多 sqlite 数据库的表的方法。
首先尝试下载并安装用于sqlite数据库的DB浏览器。然后尝试在 2 个窗口中打开数据库,并尝试通过简单地将表从一个窗口拖放到另一个窗口来合并它们。但问题是,您一次只能拖放一个表,因此它并不是专门针对此答案的解决方案,但如果您的数据库很小,它可以用于节省进一步搜索的时间。
无意冒犯,就像一个开发人员对另一个开发人员一样,我担心您的想法似乎效率极低。 在我看来,您应该在同一个数据库文件中存储多个表,而不是统一 SQLite 数据库。