我编写了一个程序,将结果以严格的纯CSV形式输出到标准输出(每行代表一条记录并包含相同的一组逗号分隔字段,字段仅包含小写英文字母、数字和点,没有空格,没有引号,也没有可能需要转义/编码的符号)。
如何将此输出重定向到完美适合的 SQLite 表中?
如果我可以控制是否要打破约束(例如与表中已有的记录具有相同的主/辅键)替换现有记录或默默地丢弃,那就太好了。
当然,我可能会在程序本身中构建直接的 SQLite 数据库输出支持,但如果可能的话,我更喜欢采用 UNIX 方式。
答案1
我找到了一个更简单的解决方案,仍然使用sqlite3
.import
,但这不会读取/dev/stdin
或临时命名管道。相反,它.import
与管道操作员调用cat -
直接从标准输入读取。
#!/bin/bash
function csv_to_sqlite() {
local database_file_name="$1"
local table_name="$2"
sqlite3 -csv $database_file_name ".import '|cat -' $table_name"
}
database_file_name=$1
table_name=$2
csv_to_sqlite "$database_file_name" "$table_name"
请注意,这在 Windows 命令 shell 中不起作用。
答案2
两种方法:
样本test.csv
文件:
GroupName,Groupcode,GroupOwner,GroupCategoryID
System Administrators,sysadmin,13456,100
Independence High Teachers,HS Teachers,,101
John Glenn Middle Teachers,MS Teachers,13458,102
Liberty Elementary Teachers,Elem Teachers,13559,103
1st Grade Teachers,1stgrade,,104
2nd Grade Teachers,2nsgrade,13561,105
3rd Grade Teachers,3rdgrade,13562,106
Guidance Department,guidance,,107
1) 和csvkit(一套用于转换和使用 CSV 的命令行工具)
导入到sqlite3数据库:
csvsql --db sqlite:///test_db --tables test_tbl --insert test.csv
如果未指定输入 csv 文件,它将接受来自 stdin 的 csv 数据:
... | csvsql --db sqlite:///test_db --tables test_tbl --insert
从中提取数据sqlite数据库:
sql2csv --db sqlite:///test_db --query 'select * from test_tbl limit 3'
输出:
GroupName,Groupcode,GroupOwner,GroupCategoryID
System Administrators,sysadmin,13456,100
Independence High Teachers,HS Teachers,,101
John Glenn Middle Teachers,MS Teachers,13458,102
2) 和sqlite3命令行工具(允许用户手动输入并执行 SQL 语句)SQLite数据库)
使用“
.import
”命令将 CSV(逗号分隔值)数据导入到 SQLite 表中。 “.import
”命令有两个参数,分别是要从中读取 CSV 数据的磁盘文件的名称和要向其中插入 CSV 数据的 SQLite 表的名称。请注意,在运行“ ”命令之前将“模式”设置为“csv”非常重要
.import
。这对于防止命令行 shell 尝试将输入文件文本解释为其他格式是必要的。
$ sqlite3
sqlite> .mode csv
sqlite> .import test.csv test_tbl
sqlite> select GroupName,Groupcode from test_tbl limit 5;
"System Administrators",sysadmin
"Independence High Teachers","HS Teachers"
"John Glenn Middle Teachers","MS Teachers"
"Liberty Elementary Teachers","Elem Teachers"
"1st Grade Teachers",1stgrade
sqlite>
答案3
在类 Unix 系统上,sqlite3
命令.import
可以从特殊文件的标准输入读取 CSV 内容/dev/stdin
:
$ printf "col1,col2\na,1\nb,2\n" | sqlite3 test.db ".import --csv /dev/stdin test"
$ sqlite3 -csv -header test.db "SELECT * FROM test"
col1,col2
a,1
$ sqlite3 -version
3.32.3 2020-06-18 14:00:33 7ebdfa80be8e8e73324b8d66b3460222eb74c7e9dfd655b48d6ca7e1933cc8fd
b,2
答案4
以下 bash 函数csv_to_sqlite
从标准输入读取 CSV 内容,并使用以下命令将其导入到 SQLite 数据库表中:sqlite3
命令.import
和一个临时命名管道(FIFO):
#!/bin/bash
function csv_to_sqlite() {
local database_file_name="$1"
local table_name="$2"
local temp_input_fifo=$(mktemp -u)
mkfifo $temp_input_fifo
sqlite3 -csv $database_file_name ".import $temp_input_fifo $table_name" &
cat > $temp_input_fifo
rm $temp_input_fifo
}
database_file_name=$1
table_name=$2
csv_to_sqlite "$database_file_name" "$table_name"
$ printf "col1,col2,col3\na,1,2.6\nb,2,5.4\n" | ./csv_to_sqlite test.sqlite test
$ sqlite3 -csv -header test.sqlite "SELECT * FROM test"
col1,col2,col3
a,1,2.6
b,2,5.4