You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Zig中用zuckdb/DuckDB Appender正确写入Timestamp类型K线数据

问题

需要向DuckDB中追加带有Timestamp类型的K线数据,目前用VARCHAR类型存储时间,希望改为TIMESTAMP类型以支持基于时间戳的查询。API返回的时间格式为2024-01-02T05:00:00Z,使用Zig语言和zuckdb库,直接将time列改为TIMESTAMP并追加字符串时会触发Appender运行时错误。

解决方案

要正确存储TIMESTAMP类型数据,需完成两步:修改表结构为TIMESTAMP列,将字符串时间解析为DuckDB兼容的时间类型后再插入。

1. 修改表结构

把historical_bar表的time列类型从VARCHAR改为TIMESTAMP:

pub fn create(conn: *zuckdb.Conn) !void {
    _ = try conn.exec(
        \\CREATE TABLE historical_bar (
        \\  symbol VARCHAR,
        \\  time TIMESTAMP,
        \\  open FLOAT,
        \\  high FLOAT,
        \\  low FLOAT,
        \\  close FLOAT,
        \\  number UINT32,
        \\  volume UINT64,
        \\  vwap FLOAT
        \\);
    , .{});
}

2. 解析时间字符串为DuckDB Timestamp类型

DuckDB的TIMESTAMP对应zuckdb库的zuckdb.Timestamp(微秒级Unix时间戳),需将API返回的RFC3339格式字符串解析为该类型:

fn parseRFC3339ToTimestamp(time_str: []const u8) !zuckdb.Timestamp {
    // 解析RFC3339格式时间
    const datetime = try std.time.parseRFC3339(time_str);
    // 转换为秒级Unix时间戳
    const unix_sec = std.time.epoch.datetimeToUnix(datetime);
    // 转成微秒级,匹配DuckDB TIMESTAMP的精度
    return @intCast(zuckdb.Timestamp, unix_sec * 1_000_000);
}

3. 修改批量追加逻辑

在插入时先将字符串时间解析为zuckdb.Timestamp,再传入Appender:

pub fn append(conn: *zuckdb.Conn, hbr: *model.HistoricalBarsResult) !void {
    var appender = try conn.appender(null, "historical_bar");
    defer appender.deinit();
    for (hbr.bars.items) |bar| {
        const timestamp = try parseRFC3339ToTimestamp(bar.time);
        appender.appendRow(.{ bar.symbol, timestamp, bar.open, bar.high, bar.low, bar.close, bar.number, bar.volume, bar.vwap }) catch |err| {
            std.debug.print("{}\n", .{bar});
            if (err == error.DuckDBError) {
                if (conn.err) |derr| {
                    std.log.err("DuckDB {s}\n", .{derr});
                } else {
                    return error.NoErrorAvailable;
                }
            } else {
                return err;
            }
        };
    }

    try appender.flush();
}

替代方案:插入时用DuckDB函数转换

如果不想在Zig中解析时间,也可以用DuckDB的STRPTIME函数在插入时直接转换字符串,不过效率略低于提前解析:

// 改用参数化查询插入
pub fn append(conn: *zuckdb.Conn, hbr: *model.HistoricalBarsResult) !void {
    const stmt = try conn.prepare(
        \\INSERT INTO historical_bar (symbol, time, open, high, low, close, number, volume, vwap)
        \\VALUES (?, STRPTIME(?, '%Y-%m-%dT%H:%M:%SZ'), ?, ?, ?, ?, ?, ?, ?)
    );
    defer stmt.deinit();
    
    for (hbr.bars.items) |bar| {
        _ = try stmt.exec(.{ bar.symbol, bar.time, bar.open, bar.high, bar.low, bar.close, bar.number, bar.volume, bar.vwap });
    }
}

内容的提问来源于stack exchange,提问作者lele1c

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 08:44:54