我正在尝试将大量数据(550万行)批量加载到SQLite数据库文件中。 通过INSERT加载似乎太慢了,所以我试图使用sqlite3命令行工具和.import命令。
如果我手动输入命令,它可以完美地工作,但我不能为我的生活找出如何从脚本(.bat文件或python脚本;我在Windows机器上工作)自动化它
我在命令行发出的命令是:
> sqlite3 database.db
sqlite> CREATE TABLE log_entry ( <snip> );
sqlite> .separator "\t"
sqlite> .import logfile.log log_entry
但是我尝试的任何东西都不会从bat文件或python脚本中运行它。
我一直在尝试这样的事情:
sqlite3 "database.db" .separator "\t" .import logfile.log log_entry
echo '.separator "\t" .import logfile.log log_entry' | sqlite3 database.db
当然我能以某种方式做到这一点?
答案 0 :(得分:52)
创建一个文本文件,其中包含您要在sqlite命令行程序中输入的行,如下所示:
CREATE TABLE log_entry ( ); .separator "\t" .import logfile.log log_entry
然后只需致电sqlite3 database.db < commands.txt
答案 1 :(得分:25)
或者,您可以使用heredoc import.sh 将所有内容放在一个shell脚本文件中(从而简化维护):
#!/bin/bash --
sqlite3 -batch $1 <<"EOF"
CREATE TABLE log_entry ( <snip> );
.separator "\t"
.import logfile.log log_entry
EOF
...并运行它:
import.sh database.db
这样可以更轻松地维护一个脚本文件。 顺便说一句,如果您需要在Windows下运行它,Power Shell also features heredoc
此外,此方法有助于处理缺少脚本参数支持。您可以使用bash变量:
#!/bin/bash --
table_name=log_entry
sqlite3 -batch $1 <<EOF
CREATE TABLE ${table_name} ( <snip> );
.separator "\t"
.import logfile.log ${table_name}
EOF
甚至可以这样做:
#!/bin/bash --
table_name=$2
sqlite3 -batch $1 <<EOF
CREATE TABLE ${table_name} ( <snip> );
.separator "\t"
.import logfile.log ${table_name}
EOF
...并运行它:import.sh database.db log_entry
答案 2 :(得分:17)
创建一个单独的文本文件,其中包含您通常在sqlite3 shell应用程序中输入的所有命令:
CREATE TABLE log_entry ( <snip> );
.separator "\t"
.import /path/to/logfile.log log_entry
将其保存为impscript.sql。
创建一个批处理文件,该文件使用该脚本调用sqlite3 shell:
sqlite3.exe yourdatabase.db < /path/to/impscript.sql
调用批处理文件。
旁注 - 导入时,确保将INSERT包装在事务中!这将使您立即获得10.000%的加速。
答案 3 :(得分:5)
我最近在将Firefox的cookies.sqlite转换为文本文件(对于某些下载工具)时遇到了类似的问题,并偶然发现了这个问题。
我想用一个shell行来做这个,这将是我的解决方案应用于上述问题:
echo -e ".mode tabs\n.import logfile.log log_entry" | sqlite3 database.db
但我还没有测试过那条线。但是我在上面提到的Firefox问题(通过Mac OSX上的Bash)中运行良好:
echo -e ".mode tabs\nselect host, case when host glob '.*' then 'TRUE' else 'FALSE' end, path, case when isSecure then 'TRUE' else 'FALSE' end, expiry, name, value from moz_cookies;" | sqlite3 cookies.sqlite
答案 4 :(得分:2)
sqlite3 abc.db ".read scriptname.sql"
答案 5 :(得分:1)
此时,我不确定除了之外我还能添加什么,我在向nad2000建议的bash脚本添加unix环境变量时遇到了一些麻烦。
运行这个:
bash dbmake.sh database.db <(sed '1d' $DATA/logfile.log | head -n 1000)
我需要从stdin导入作为解决方法,我找到了这个解决方案:
sqlite3 $1 <<"EOF"
CREATE TABLE log_entry;
EOF
sqlite3 -separator $'\t' $1 ".import $2 log_entry"
通过添加第二个sqlite3行,我能够将$ 2中的$ 2传递给.import,完整路径和所有内容的文件参数。
答案 6 :(得分:0)
在Windows上,这应该有效:
(echo CREATE TABLE log_entry ( <snip> ); & echo .separator "\t" & echo .import logfile.log log_entry) | sqlite3.exe database.db
我没有测试过这个特殊的命令,但是我自己追求解决这个管道多个命令的问题,我发现关键是将回显的命令括在括号中。话虽这么说,你可能需要调整上面的命令来逃避其中的一些字符。例如:
(echo CREATE TABLE log_entry ^( ^<snip^> ^); & echo .separator "\t" & echo .import logfile.log log_entry) | sqlite3.exe database.db
我不确定在这种情况下是否需要转义,但很可能因为括号可能与封闭的那些冲突,然后“小于”和“大于“符号通常被解释为输入或输出,这也可能会发生冲突。可以在此处找到大量字符的转义:http://www.robvanderwoude.com/escapechars.php
答案 7 :(得分:-1)
here trans is table name and trans.csv is a csv file in which i have 1959 rows of data
$ sqlite3 abc.db ".separator ','"
$ sqlite3 abc.db ".import 'trans.csv' trans"
$ sqlite3 abc.db "select count(*) from trans;"
1959
但不可能像你写的那样写作