如何用Perl自动批量导入JSON文件到DuckDB?无DBD驱动方案
实现思路
方案1:调用DuckDB命令行工具
Perl可以直接执行DuckDB的命令行命令,通过系统调用传递SQL语句,这是无需额外驱动的最直接方案。
示例代码:
use strict; use warnings; # 第一步:用第一个JSON文件创建表 my $create_table_cmd = qq{duckdb mydatabase.db -c "CREATE TABLE mytable AS SELECT * FROM read_json_auto('input1.json')"}; system($create_table_cmd) == 0 or die "创建表失败: $?"; # 第二步:遍历其余JSON文件插入数据 my @other_files = qw(input2.json input3.json ...); # 替换为你的目标文件列表 foreach my $file (@other_files) { # 转义文件路径中的特殊字符(如空格)避免命令出错 my $escaped_file = quotemeta($file); my $insert_cmd = qq{duckdb mydatabase.db -c "INSERT INTO mytable SELECT * FROM read_json_auto('$escaped_file')"}; system($insert_cmd) == 0 or die "插入文件 $file 失败: $?"; }
如果需要捕获命令输出或错误信息,可改用IPC::Run或IPC::Open3模块替代system,实现更精细的交互控制。
方案2:用Inline::C调用DuckDB的C API
若要避免频繁启动命令行进程、追求更高交互效率,可借助Perl的Inline::C模块直接调用DuckDB的C语言API,实现Perl与DuckDB的直接对接。
示例代码框架:
use strict; use warnings; use Inline 'C'; # 初始化DuckDB连接 my $db; my $connection; duckdb_open("mydatabase.db", \$db); duckdb_connect($db, \$connection); # 执行创建表的SQL my $create_sql = "CREATE TABLE mytable AS SELECT * FROM read_json_auto('input1.json')"; my $result; duckdb_query($connection, $create_sql, \$result); duckdb_destroy_result($result); # 遍历插入其他文件 my @other_files = qw(input2.json input3.json ...); foreach my $file (@other_files) { my $insert_sql = "INSERT INTO mytable SELECT * FROM read_json_auto('$file')"; duckdb_query($connection, $insert_sql, \$result); duckdb_destroy_result($result); } # 清理资源 duckdb_disconnect($connection); duckdb_close($db); __END__ __C__ #include <duckdb.h> void duckdb_open(char *db_path, duckdb *out_db) { duckdb_open(db_path, out_db); } void duckdb_connect(duckdb db, duckdb_connection *out_conn) { duckdb_connect(db, out_conn); } void duckdb_query(duckdb_connection conn, char *sql, duckdb_result *out_result) { duckdb_query(conn, sql, out_result); } void duckdb_destroy_result(duckdb_result result) { duckdb_destroy_result(&result); } void duckdb_disconnect(duckdb_connection conn) { duckdb_disconnect(&conn); } void duckdb_close(duckdb db) { duckdb_close(&db); }
使用该方案需确保系统已安装DuckDB开发库,且Inline::C能正确链接到该库。
方案3:合并JSON文件后一次性导入
若所有JSON文件格式一致,可先在Perl中将所有文件合并为一个符合要求的JSON文件,再一次性导入DuckDB,减少操作次数。此方案适合文件体积较小的场景,避免内存占用过高。
示例代码(合并为JSON数组):
use strict; use warnings; use JSON; my @all_files = ('input1.json', 'input2.json', ...); my @all_data; foreach my $file (@all_files) { open my $fh, '<', $file or die "无法打开 $file: $!"; my $content = do { local $/; <$fh> }; my $data = decode_json($content); # 统一格式:单个对象转为数组元素,数组则直接展开 push @all_data, ref $data eq 'ARRAY' ? @$data : $data; close $fh; } # 写入合并后的文件 open my $out_fh, '>', 'combined.json' or die "无法写入 combined.json: $!"; print $out_fh encode_json(\@all_data); close $out_fh; # 导入到DuckDB system(qq{duckdb mydatabase.db -c "CREATE TABLE mytable AS SELECT * FROM read_json_auto('combined.json')"}) == 0 or die "导入合并文件失败: $?";
内容的提问来源于stack exchange,提问作者dave
相关产品推荐
相关产品推荐

