数据库查询与导出Skill database-query-and-export

这个技能用于查询SQLite、PostgreSQL和MySQL数据库,并将结果导出到CSV或JSON格式。适用于数据提取、报告生成、备份迁移、数据分析工作流和自动化数据库查询。关键词包括数据库查询、数据导出、CSV导出、JSON导出、SQLite、PostgreSQL、MySQL、数据工程、ETL。

数据工程 0 次安装 0 次浏览 更新于 3/22/2026

name: 数据库查询与导出 description: “查询SQLite、PostgreSQL和MySQL数据库并导出结果到CSV/JSON。使用场景:(1) 提取数据用于报告,(2) 数据库备份和迁移,(3) 数据分析工作流,或(4) 自动化数据库查询。”

数据库查询与导出

查询关系型数据库(SQLite、PostgreSQL、MySQL)并将结果导出到CSV、JSON或其他格式。对于数据提取、报告、备份自动化和分析流程至关重要。

何时使用

  • 使用场景1:当用户要求查询数据库并导出结果时
  • 使用场景2:当需要提取数据用于分析或报告时
  • 使用场景3:用于备份和数据迁移工作流
  • 使用场景4:当构建自动化数据库监控和警报时

所需工具/API

  • SQLite — 轻量级基于文件的数据库(通常预安装)
  • PostgreSQL客户端 — 用于PostgreSQL数据库
  • MySQL客户端 — 用于MySQL/MariaDB数据库
  • 无需外部API

安装选项:

# Ubuntu/Debian
sudo apt-get install -y sqlite3 postgresql-client mysql-client

# macOS
brew install sqlite3 postgresql mysql-client

# Node.js(数据库驱动)
npm install better-sqlite3  # SQLite
npm install pg              # PostgreSQL
npm install mysql2          # MySQL

技能

query_sqlite_to_json

查询SQLite数据库并导出为JSON格式。

# 基本查询到JSON
sqlite3 database.db "SELECT * FROM users LIMIT 10;" -json

# 使用jq进行漂亮格式化
sqlite3 database.db "SELECT * FROM users WHERE active=1;" -json | jq '.'

# 导出整个表到JSON文件
sqlite3 database.db "SELECT * FROM orders;" -json > orders.json

# 使用WHERE子句查询
sqlite3 database.db "SELECT id, name, email FROM users WHERE created_at > '2024-01-01';" -json

Node.js:

const Database = require('better-sqlite3');

function querySQLiteToJSON(dbPath, query) {
  const db = new Database(dbPath, { readonly: true });
  const rows = db.prepare(query).all();
  db.close();
  return rows;
}

// 用法
// const users = querySQLiteToJSON('./database.db', 'SELECT * FROM users LIMIT 10');
// console.log(JSON.stringify(users, null, 2));

query_sqlite_to_csv

查询SQLite数据库并导出为CSV格式。

# 基本查询到CSV
sqlite3 database.db <<EOF
.mode csv
.headers on
SELECT * FROM users LIMIT 10;
EOF

# 导出到CSV文件
sqlite3 database.db <<EOF
.mode csv
.headers on
.output users.csv
SELECT id, name, email, created_at FROM users WHERE active=1;
EOF

# 使用JOIN查询多个表
sqlite3 database.db <<EOF
.mode csv
.headers on
SELECT u.name, o.order_id, o.total 
FROM users u 
JOIN orders o ON u.id = o.user_id 
WHERE o.created_at > '2024-01-01';
EOF

Node.js:

const Database = require('better-sqlite3');
const fs = require('fs');

function querySQLiteToCSV(dbPath, query, outputPath) {
  const db = new Database(dbPath, { readonly: true });
  const rows = db.prepare(query).all();
  db.close();
  
  if (rows.length === 0) {
    return '没有结果';
  }
  
  // 生成CSV
  const headers = Object.keys(rows[0]).join(',');
  const csvRows = rows.map(row => 
    Object.values(row).map(val => 
      typeof val === 'string' && val.includes(',') ? `"${val}"` : val
    ).join(',')
  );
  
  const csv = [headers, ...csvRows].join('
');
  
  if (outputPath) {
    fs.writeFileSync(outputPath, csv);
    return `已导出 ${rows.length} 行到 ${outputPath}`;
  }
  
  return csv;
}

// 用法
// querySQLiteToCSV('./database.db', 'SELECT * FROM users LIMIT 10', './users.csv');

query_postgresql

查询PostgreSQL数据库并导出结果。

# 设置连接字符串(替代:使用单独标志)
export PGHOST=localhost
export PGPORT=5432
export PGDATABASE=mydb
export PGUSER=postgres
export PGPASSWORD=mypassword

# 查询到JSON(使用psql格式化输出)
psql -t -A -F"," -c "SELECT row_to_json(t) FROM (SELECT * FROM users LIMIT 10) t;"

# 查询到CSV
psql -c "COPY (SELECT * FROM users WHERE active=true) TO STDOUT WITH CSV HEADER;" > users.csv

# 使用连接字符串查询
psql "postgresql://user:password@localhost:5432/mydb" -c "SELECT * FROM users LIMIT 5;"

# 查询到格式化表格
psql -c "SELECT id, name, email FROM users ORDER BY created_at DESC LIMIT 10;"

Node.js:

const { Pool } = require('pg');

async function queryPostgreSQL(connectionString, query) {
  const pool = new Pool({ connectionString });
  
  try {
    const result = await pool.query(query);
    return result.rows;
  } finally {
    await pool.end();
  }
}

// 用法
// const connStr = 'postgresql://user:password@localhost:5432/mydb';
// queryPostgreSQL(connStr, 'SELECT * FROM users LIMIT 10')
//   .then(rows => console.log(JSON.stringify(rows, null, 2)));

query_mysql

查询MySQL/MariaDB数据库并导出结果。

# 查询到CSV带标题
mysql -h localhost -u root -p'mypassword' -D mydb \
  -e "SELECT * FROM users WHERE active=1;" \
  --batch --silent \
  | cat > users.csv

# 查询到类JSON格式(需要jq进行适当格式化)
mysql -h localhost -u root -p'mypassword' -D mydb \
  -e "SELECT * FROM users LIMIT 10;" \
  --batch --silent

# 导出整个表到CSV
mysql -h localhost -u root -p'mypassword' -D mydb \
  -e "SELECT * FROM orders INTO OUTFILE '/tmp/orders.csv' 
      FIELDS TERMINATED BY ',' 
      ENCLOSED BY '\"' 
      LINES TERMINATED BY '
';"

# 带超时查询
mysql -h localhost -u root -p'mypassword' -D mydb \
  --connect-timeout=10 \
  -e "SELECT COUNT(*) as total FROM users;"

Node.js:

const mysql = require('mysql2/promise');

async function queryMySQL(config, query) {
  const connection = await mysql.createConnection({
    host: config.host || 'localhost',
    user: config.user,
    password: config.password,
    database: config.database,
    connectTimeout: 10000
  });
  
  try {
    const [rows] = await connection.execute(query);
    return rows;
  } finally {
    await connection.end();
  }
}

// 用法
// const config = {
//   host: 'localhost',
//   user: 'root',
//   password: 'mypassword',
//   database: 'mydb'
// };
// queryMySQL(config, 'SELECT * FROM users LIMIT 10')
//   .then(rows => console.log(JSON.stringify(rows, null, 2)));

advanced_sqlite_export_with_error_handling

生产就绪的SQLite导出,带验证和错误处理。

#!/bin/bash
DB_PATH="database.db"
QUERY="SELECT * FROM users WHERE active=1;"
OUTPUT_FILE="users.csv"

# 检查数据库是否存在
if [ ! -f "$DB_PATH" ]; then
  echo "错误:数据库文件未找到: $DB_PATH" >&2
  exit 1
fi

# 检查表是否存在
if ! sqlite3 "$DB_PATH" "SELECT name FROM sqlite_master WHERE type='table' AND name='users';" | grep -q "users"; then
  echo "错误:数据库中未找到表 'users'" >&2
  exit 1
fi

# 执行查询并导出到CSV
if sqlite3 "$DB_PATH" <<EOF > "$OUTPUT_FILE" 2>&1
.mode csv
.headers on
$QUERY
EOF
then
  ROW_COUNT=$(wc -l < "$OUTPUT_FILE")
  echo "成功:已导出 $((ROW_COUNT - 1)) 行到 $OUTPUT_FILE"
else
  echo "错误:查询失败" >&2
  exit 1
fi

Node.js:

const Database = require('better-sqlite3');
const fs = require('fs');

async function exportSQLiteWithValidation(options) {
  const { dbPath, query, outputPath, format = 'json' } = options;
  
  // 验证数据库存在
  if (!fs.existsSync(dbPath)) {
    throw new Error(`数据库文件未找到: ${dbPath}`);
  }
  
  let db;
  try {
    db = new Database(dbPath, { readonly: true, timeout: 10000 });
    
    // 准备并执行查询
    const stmt = db.prepare(query);
    const rows = stmt.all();
    
    if (rows.length === 0) {
      return { success: true, rowCount: 0, message: '没有返回行' };
    }
    
    // 基于格式导出
    let output;
    if (format === 'json') {
      output = JSON.stringify(rows, null, 2);
    } else if (format === 'csv') {
      const headers = Object.keys(rows[0]).join(',');
      const csvRows = rows.map(row => 
        Object.values(row).map(val => 
          typeof val === 'string' && val.includes(',') ? `"${val.replace(/"/g, '""')}"` : val
        ).join(',')
      );
      output = [headers, ...csvRows].join('
');
    } else {
      throw new Error(`不支持格式: ${format}`);
    }
    
    // 写入文件
    fs.writeFileSync(outputPath, output);
    
    return {
      success: true,
      rowCount: rows.length,
      outputPath,
      format,
      message: `已导出 ${rows.length} 行到 ${outputPath}`
    };
    
  } catch (err) {
    throw new Error(`数据库导出失败: ${err.message}`);
  } finally {
    if (db) db.close();
  }
}

// 用法
// exportSQLiteWithValidation({
//   dbPath: './database.db',
//   query: 'SELECT * FROM users WHERE active=1',
//   outputPath: './users.json',
//   format: 'json'
// }).then(result => console.log(result));

速率限制/最佳实践

  • 使用只读连接 — 在只查询时以只读模式打开数据库
  • 设置连接超时 — 使用10-30秒超时防止挂起
  • 验证输入 — 在查询前检查数据库文件/表是否存在
  • 转义用户输入 — 使用参数化查询防止SQL注入
  • 处理大数据集 — 对大表使用LIMIT/OFFSET进行分页
  • 关闭连接 — 查询后始终关闭数据库连接
  • ⚠️ 安全凭证 — 将数据库密码存储在环境变量中,永不硬编码
  • ⚠️ 导出文件权限 — 确保导出目录具有适当的写入权限

代理提示

您具备数据库查询和导出能力。当用户要求查询数据库时:

1. 从以下识别数据库类型(SQLite、PostgreSQL、MySQL):
   - 文件扩展名(.db、.sqlite、.sqlite3 = SQLite)
   - 连接字符串(postgresql://、mysql://)
   - 用户指定

2. 对于SQLite:
   - 使用 `sqlite3 database.db "QUERY" -json` 用于JSON输出
   - 使用 `.mode csv` 和 `.headers on` 用于CSV输出
   - 始终首先检查数据库文件是否存在

3. 对于PostgreSQL:
   - 使用 `psql` 带连接字符串或环境变量
   - 使用 `COPY ... TO STDOUT WITH CSV HEADER` 用于CSV导出
   - 使用 `row_to_json()` 函数导出JSON

4. 对于MySQL:
   - 使用 `mysql` 带 `-e` 标志进行查询
   - 使用 `--batch --silent` 用于类CSV输出
   - 使用 `--connect-timeout=10` 设置连接超时

5. 始终:
   - 在查询前验证数据库/表是否存在
   - 在只读时使用只读连接
   - 优雅处理错误并给出清晰消息
   - 清理输出(在CSV中转义逗号,引用字符串)

6. 对于大数据集:
   - 向查询添加LIMIT子句
   - 对非常大的表使用OFFSET分页
   - 如果结果集可能很大,警告用户

故障排除

错误:“无法打开数据库文件”

  • 症状:SQLite无法找到或访问数据库文件
  • 解决方案:检查文件路径是否正确以及文件是否有读取权限

错误:“连接被拒绝”

  • 症状:无法连接到PostgreSQL或MySQL服务器
  • 解决方案:验证主机/端口是否正确,数据库服务正在运行,防火墙允许连接

错误:“认证失败”

  • 症状:数据库拒绝用户名/密码
  • 解决方案:验证凭证是否正确,用户具有必要权限

错误:“表不存在”

  • 症状:查询引用不存在的表
  • 解决方案:首先列出可用表(sqlite3 db.db ".tables" 或在psql中使用 \dt

CSV输出格式损坏:

  • 症状:数据中的逗号破坏CSV列
  • 解决方案:正确使用引号转义含逗号的值,转义现有引号

查询时间过长:

  • 症状:查询挂起或运行数分钟
  • 解决方案:添加LIMIT子句,使用索引优化查询,增加超时

另请参阅