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

如何用rusqlite简化SELECT语句并实现SQLite列模式表格展示?

问题描述

我正在开发一款使用rusqlite及多条SQLite语句的应用,现需简化SELECT查询语句并优化输出格式。当前使用的Rust代码如下:

let mut stmt = conn.prepare("SELECT pid, cat, plant, variety FROM plants")?;

println!("Columns  = {:?}", stmt.column_names());
println!("column 0 = {:?}", stmt.column_names()[0]);

// ************************MAP the rows using Plant struct
let plant_iter = stmt.query_map([], |row| {
    Ok(Plant {
        pid: row.get(0)?,
        cat: row.get(1)?,
        plant: row.get(2)?,
        variety: row.get(3)?,
    })
})?;

println!(); // ********************ITERATE over the mapped rows using struct
for plant in plant_iter {
    print!(
        "{}{} ",
        plant.as_ref().unwrap().pid,
        " ".repeat(4 - plant.as_ref().unwrap().pid.to_string().len())
    );
    print!(
        "{}{} ",
        plant.as_ref().unwrap().cat,
        " ".repeat(8 - plant.as_ref().unwrap().cat.to_string().len())
    );
    print!(
        "{}{} ",
        plant.as_ref().unwrap().plant,
        " ".repeat(10 - plant.as_ref().unwrap().plant.to_string().len())
    );
    print!(
        "{}{} ",
        plant.as_ref().unwrap().variety,
        " ".repeat(20 - plant.as_ref().unwrap().variety.to_string().len())
    );
}

当前输出结果:

Columns  = ["pid", "cat", "plant", "variety"]
column 0 = "pid"

1    veggie   tomato     Brandywine           
2    veggie   bok choy   prize                
3    veggie   cabbage    brunswick            

希望实现类似SQLite中.mode column的格式,即一次性输出带表头且列间距美观的表格,请问如何通过rusqlite将列表头与行数据结合,模拟SQLite的表格视图?

解决方案

可以通过计算自适应列宽+统一格式化输出的方式实现,具体步骤如下:

  1. 先获取查询的列名,再收集所有行数据,计算每一列的最大宽度(表头长度与所有行对应字段长度的最大值),确保列间距能自适应内容。
  2. 按照计算好的列宽,先输出格式化后的表头,再输出分隔线(可选),最后逐行格式化输出数据。

完整实现代码:

use rusqlite::{Connection, Result};

#[derive(Debug)]
struct Plant {
    pid: i32,
    cat: String,
    plant: String,
    variety: String,
}

fn main() -> Result<()> {
    let conn = Connection::open("plants.db")?;

    // 准备查询并获取列名
    let mut stmt = conn.prepare("SELECT pid, cat, plant, variety FROM plants")?;
    let column_names = stmt.column_names().to_vec();
    
    // 收集所有行数据,用于计算列宽
    let mut plants = Vec::new();
    let plant_iter = stmt.query_map([], |row| {
        Ok(Plant {
            pid: row.get(0)?,
            cat: row.get(1)?,
            plant: row.get(2)?,
            variety: row.get(3)?,
        })
    })?;
    for plant in plant_iter {
        plants.push(plant?);
    }

    // 计算每一列的最大宽度:表头长度 vs 所有行对应字段的长度
    let mut column_widths: Vec<usize> = column_names
        .iter()
        .map(|name| name.len())
        .collect();
    
    for plant in &plants {
        column_widths[0] = column_widths[0].max(plant.pid.to_string().len());
        column_widths[1] = column_widths[1].max(plant.cat.len());
        column_widths[2] = column_widths[2].max(plant.plant.len());
        column_widths[3] = column_widths[3].max(plant.variety.len());
    }

    // 输出格式化表头
    for (i, name) in column_names.iter().enumerate() {
        print!("{name:<width$} ", width = column_widths[i] + 2); // 额外添加2个空格作为列间距
    }
    println!();

    // 输出分隔线(可选,模拟SQLite的视觉效果)
    for &width in &column_widths {
        print!("{} ", "-".repeat(width));
    }
    println!();

    // 逐行输出格式化数据
    for plant in plants {
        print!("{:<width$} ", plant.pid, width = column_widths[0] + 2);
        print!("{:<width$} ", plant.cat, width = column_widths[1] + 2);
        print!("{:<width$} ", plant.plant, width = column_widths[2] + 2);
        println!("{:<width$} ", plant.variety, width = column_widths[3] + 2);
    }

    Ok(())
}

代码说明

  • 收集数据计算列宽:先把所有行数据存入Vec,避免重复遍历查询结果,确保能准确计算每一列的最大宽度,让列间距自适应内容长度。
  • 格式化输出:使用Rust格式化语法{:<width$}实现左对齐并填充空格,额外添加2个空格作为列间距,和SQLite .mode column的视觉效果一致。
  • 分隔线:可选的分隔线能让表头和数据区分更清晰,进一步贴近SQLite的输出样式。

最终输出效果

pid  cat     plant     variety  
---  ------  --------  ----------
1    veggie  tomato    Brandywine
2    veggie  bok choy  prize     
3    veggie  cabbage   brunswick 

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 15:54:53