管道字符串,文件内容,字符串到没有中间文件的sqlite?

Pipe string, file contents, string into sqlite without intermediate file?

我有这个 shell 脚本,它采用一组 INSERT 语句并在开始处放置一个 'BEGIN TRANSACTION',在结尾放置一个 'COMMIT'。有 lot 个 INSERT 语句,因此这使得插入速度更快。

我使用成功的脚本是这样的

file_name_improved_sql=foo-improved.sql
file_name_original_sql=foo.sql
file_name_sqlite_db=bar.db
path_to_insert_error=/tmp/fooerrors.log
#
echo 'BEGIN TRANSACTION;' | cat - $file_name_original_sql  > $file_name_improved_sql 
echo "COMMIT;" >> $file_name_improved_sql
#
cat $file_name_improved_sql | sqlite3 $file_name_sqlite_db 2> $path_to_insert_error

我想改进这一点,这样就不会生成中间文件 file_name_improved_sql,直接通过管道输入两个字符串和文件内容。

像这样的东西(除了这不起作用)...

export string1="BEGIN TRANSACTION"
export string2="COMMIT"
cat $string1 $file_name_improved_sql $string2 | sqlite3 $file_name_sqlite_db 2> $path_to_insert_error

如有任何建议,我们将不胜感激。

sqlite3 shell 中的 .read 命令需要一个文件名来读取命令。如果该名称以竖线字符开头,它将被视为 shell 命令而不是文件名,并从该命令的标准输出中读取。

所以你可以做类似的事情

sqlite3 "$file_name_sqlite_db" ".read '|echo \"BEGIN TRANSACTION;\"; cat \"file_name_original_sql\"; echo \"COMMIT;\"'"

改用 heredoc 有助于简化引用:

sqlite3 "$file_name_sqlite.db" <<EOF
.read '|echo "BEGIN TRANSACTION;"; cat "$file_name_original.sql"; echo "COMMIT;"'
EOF

组命令并将整个组重定向到管道 sqlite3:

{
  printf %s\n 'BEGIN TRANSACTION;'
  cat "$file_name_original_sql"
  printf %s\n 'COMMIT;'
} | sqlite3 "$file_name_sqlite_db" 2> "$path_to_insert_error"

要么使用此处文档作为 sqlite3 的输入:

sqlite3 "$file_name_sqlite_db" 2> "$path_to_insert_error" <<EOF
BEGIN TRANSACTION
$(cat "$file_name_original_sql")
COMMIT;
EOF

或使用 printf 组合管道传输到 sqlite3 的元素:

printf 'BEGIN TRANSACTION;\n%sCOMMIT;\n' "$(cat "$file_name_original_sql")" |
  sqlite3 "$file_name_sqlite_db" 2> "$path_to_insert_error"

或者创建一个函数来将 SQL 输入流构建到事务中:

sql_transaction() {
  printf %s\n 'BEGIN TRANSACTION;'
  cat
  printf %s\n 'COMMIT;'
}

sql_transaction <"$file_name_original_sql" |
  sqlite3 "$file_name_sqlite_db" 2> "$path_to_insert_error"