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

通用MySQL CSV文件加载Shell脚本开发可行性问询

你的通用MySQL批量导入方案完全可行!

首先得说,把所有字段统一设为varchar(256)这个思路太务实了——毕竟几十份CSV列结构各不相同,挨个分析字段类型纯纯是浪费时间。varchar(256)能覆盖绝大多数文本、数字甚至短日期的存储需求,后续要是觉得需要优化字段类型(比如把数字列改成int或者decimal),再单独调整也完全没问题,丝毫不影响批量导入的效率。

接下来给你一套完整的实现方案,直接就能用:

一、通用MySQL Shell脚本实现

我写了一个可参数化的JavaScript脚本(MySQL Shell支持JS模式,用起来比SQL脚本灵活多了),能自动遍历指定目录下的CSV,建表+导入一步到位:

1. 脚本代码

// MySQL Shell 批量CSV导入脚本
// 运行方式:mysqlsh -u 你的用户名 -p 你的密码 -h 数据库地址 --execute "source csv_import.js" -- --csv-dir="/你放CSV的目录路径"

// 解析命令行传入的CSV目录参数
const args = shell.options.args;
const csvDir = args['csv-dir'] || '.'; // 默认当前目录

// 引入文件系统模块,用来读取CSV文件
const fs = require('fs');
const path = require('path');

// 确保已连接到目标数据库(如果没提前连接,就自动连接)
if (!session.isConnected()) {
    session.connect({
        user: 'your_db_user',
        password: 'your_db_pwd',
        host: 'your_db_host',
        port: 3306,
        schema: 'your_target_schema' // 替换成你要导入的数据库名
    });
}

// 筛选出目录下所有CSV文件
const csvFiles = fs.readdirSync(csvDir).filter(file => file.toLowerCase().endsWith('.csv'));

if (csvFiles.length === 0) {
    print('没有找到任何CSV文件!');
    exit();
}

// 逐个处理CSV文件
csvFiles.forEach(file => {
    const fullPath = path.join(csvDir, file);
    // 生成合法的表名:去掉.csv后缀,把特殊字符换成下划线
    const tableName = file.replace(/\.csv$/i, '').replace(/[^a-zA-Z0-9_]/g, '_');
    
    // 读取CSV第一行作为字段名
    try {
        const fileContent = fs.readFileSync(fullPath, 'utf8');
        const firstLine = fileContent.split('\n')[0]?.trim();
        if (!firstLine) {
            print(`警告:${file}是空文件,跳过处理\n`);
            return;
        }
        
        // 处理字段名,转成MySQL合法列名,同时指定类型为varchar(256)
        const columns = firstLine.split(',').map(col => {
            const cleanColName = col.replace(/[^a-zA-Z0-9_]/g, '_').trim();
            // 避免字段名是MySQL关键字,加反引号
            return `\`${cleanColName}\` varchar(256)`;
        }).join(', ');
        
        // 创建表(IF NOT EXISTS避免重复创建报错)
        const createSql = `CREATE TABLE IF NOT EXISTS \`${tableName}\` (${columns}) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;`;
        print(`正在创建表:${tableName}`);
        session.sql(createSql).execute();
        
        // 导入数据,处理带引号的字段和换行
        const loadSql = `
            LOAD DATA INFILE '${fullPath.replace(/\\/g, '/')}'
            INTO TABLE \`${tableName}\`
            FIELDS TERMINATED BY ','
            ENCLOSED BY '"'
            ESCAPED BY '\\'
            LINES TERMINATED BY '\\n'
            IGNORE 1 ROWS;
        `;
        print(`正在导入数据到${tableName}...`);
        session.sql(loadSql).execute();
        
        print(`${file}处理完成!\n`);
    } catch (err) {
        print(`处理${file}出错:${err.message}\n`);
    }
});

print('所有CSV文件处理完毕!');

2. 关键注意事项

  • 文件权限:MySQL服务器需要能读取你的CSV文件,最简单的办法是把CSV放到MySQL配置里secure_file_priv指定的目录;要是嫌麻烦,也可以改成LOAD DATA LOCAL INFILE(从客户端读取文件),但需要确保MySQL客户端开启了local_infile=ON参数
  • 特殊字符处理:脚本会自动把字段名和表名里的特殊字符换成下划线,还加了反引号避免和MySQL关键字冲突
  • CSV格式兼容:默认处理逗号分隔、双引号包裹字段的标准CSV,如果你的CSV用了其他分隔符(比如制表符),修改FIELDS TERMINATED BY的值就行

二、额外提速小技巧

  • 事务包裹:如果CSV文件比较大,可以在导入前执行START TRANSACTION;,导入完再COMMIT;,减少磁盘IO的次数
  • 关闭约束检查:临时关闭foreign_key_checks和unique_checks,导入完再打开,能大幅提升导入速度(适合没有外键依赖的场景)
  • 并行处理:要是服务器性能够,也可以把脚本改成并行处理多个CSV,但单线程对几十份文件来说已经足够快了

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:50:27