前文介紹了數據量較小的excel表導入數據庫的方法,在數據量較大的情況下就不太適合了,一個是因為mysql命令的執行串長度有限制,二是node-xlsx這個模塊加載excel文件是整個文件全部加載到內存,在excel文件較大和可用內存受限的場景就不適合了。我們可以考慮流式讀取excel數據,分批次導入數據到數據庫。以下是以每批500條記錄的示例:
const XLSX = require('xlsx-extract').XLSX;const mysql = require("mysql2/promise"); const localpool= mysql.createPool({host:"127.0.0.1",port:3306,user:"demouser",password:"XXXXXX",database:"demodb",jsonStrings: true,waitForConnections: true,connectionLimit: 4,enableKeepAlive: true, keepAliveInitialDelay: 5000,});const batchsize=500;let count=0;
let frist=true;
let batarr=[];
let fieldnames="";
let fieldcounts=0;new XLSX().extract(process.argv.slice(2)[0], {sheet_id:1}).on('row', function (row) {if (frist) { frist=false; fieldcounts=row.length; fieldnames=row.join(); }else {for (let j=row.length;j<fieldcounts;j++) row.push("");batarr.push(row);if (batarr.length==batchsize) { let addrecs = "insert into demodb.demotable("+fieldnames+") values ?"; localpool.query(addrecs,[batarr]).then(([results])=>{ console.log(results); batarr=[];}).catch(err=>{console.log(err);});}}}).on('error', function (err) {console.error('error', err);}).on('end', function (err) {if (batarr.length>0) { let addrecs = "insert into demodb.demotable("+fieldnames+") values ?"; localpool.query(addrecs,[batarr]).then(([results])=>{ console.log(results); }).catch(err=>{console.log(err);});}});
xlsx-extract這個模塊讀取行數據時,中間的空白單元會解析成undefined,但是最后一個有值的單元后就截止了,為了和數據庫里的字段數保持一致,要將剩余的字段賦值下,示例中賦值為空字符串。
這樣可以導入excel大文件進數據庫。
其實這樣導入數據效率比直接將csv或json文件直接導入mysql效率要低很多,不過有時候轉的csv文件或者json文件導入mysql會出現報錯情況,需要檢查字段值,數據量較大時檢查會很麻煩,所以這樣導入數據也是不得已的辦法。