【问题标题】:Using CSV file in node-sqlite3 package在 node-sqlite3 包中使用 CSV 文件
【发布时间】:2019-01-15 23:43:49
【问题描述】:

我在我的网络应用程序中使用 npm sqlite3 包作为模拟餐厅(用于学习目的)。在我当前的实现中,当我的本地服务器启动时,我正在创建一个menuItems 表,如下所示:

var db = new sqlite3.Database(':memory:');
db.serialize(function() {
  db.run('CREATE TABLE menuItems ('
          + 'itemName VARCHAR(255),'
          + 'itemDescription VARCHAR(255),'
          + 'unitPrice REAL'
          + ');')
  .run("INSERT INTO menuItems (itemName, itemDescription, unitPrice) VALUES"
          + " ('Fish Filet', 'Yummy fish in a sandwich.', 9.95)")
});

但是,我希望我的 menuItems 表不被硬编码到 js 文件中,并且希望实际项目与此 js 文件分开。有几个我能想到的解决方案:

  1. 使用当前实现和硬编码命令将单个项目插入表中。

  2. 使用SQLite3导入csv文件并插入到表中。*

  3. csv 文件中读取项目并通过循环插入它们。

  4. 在服务器启动之前建立数据库并将其传递给sqlite3.Database() 构造函数。

*我想选择选项 2。但是,由于这是出于学习目的,我愿意接受任何建议,包括但不限于使用不同的数据库管理包或使用不同的类型文件(可能只是一个txt 文件或其他东西)。

我知道有some ways 可以使用SQLite3 导入csv 文件。我正在尝试做同样的事情,但来自sqlite3 npm 包。当我尝试通过链接页面中的相同命令(这似乎是特定于 sqlite3 的命令)导入文件时,

db.run('.import "C:/Users/path/to/csv/file.csv"'
      + 'INTO TABLE menuItems'
      + 'FIELDS TERMINATED BY ","'
      + 'ENCLOSED BY "\'"'
      + 'LINES TERMINATED BY \'\\n\''
      + 'IGNORE 1 ROWS'
      + ');');

我收到错误提示

events.js:183
  throw er; // Unhandled 'error' event
  ^

Error: SQLITE_ERROR: near ".": syntax error

尝试使用normal SQL syntax

    .run('BULK INSERT menuItems'
          + 'FROM "C:/Users/path/to/csv/file.csv" '
          + 'WITH '
          + '{ '
          + 'FIRSTROW = 2,'
          + 'FIELDTERMINATOR = ","'
          + 'ROWTERMINATOR = "\n",'
          + 'ERRORFILE = "C:/Users/path/to/csv/error_file.csv" '
          + 'TABLOCK'
          + '}')

我收到错误提示

events.js:183
      throw er; // Unhandled 'error' event
      ^

Error: SQLITE_ERROR: near "BULK": syntax error

我的语法有什么不正确的吗?有没有更好/工作/更有效的方法来做到这一点?选项 3 似乎可行,但我还没有尝试过。

【问题讨论】:

  • 能分享一下实现的代码吗?我一直在这样做,但仍然出现错误。

标签: node.js sqlite node-sqlite3


【解决方案1】:

有一个小例子可以将你的 csv 读入 sqlite3 db。

const sql3 = require('better-sqlite3');
const   db = new sql3( 'memory.db' );
const  csv = require('csv-parser');
const   fs = require('fs');

// create table
db.exec( 'CREATE TABLE IF NOT EXISTS menuItems ( itemName TEXT, itemDescription TEXT, unitPrice REAL );' );
//db.exec( 'DROP TABLE menuItems;' );

const insrow = db.prepare( 'insert into menuItems ( itemName, itemDescription, unitPrice ) VALUES (?, ?, ?)' );


fs.createReadStream('C:/Users/path/to/csv/file.csv')
  .pipe(csv({"separator":";"}))
  .on('data', (row) => {
    
    insrow.run( row.itemName, row.itemDescription, row.unitPrice );
    console.log(row);
  })
  .on('end', () => {
    console.log('CSV file successfully processed');
    db.close();
  });
      

例子中的数据库是memory.db,csv格式不是逗号分隔,而是分号分隔,如果需要的话可以换个分隔符。

这种情况下的 csv 必须以 itemName;itemDescription;unitPrice 标题开头,并且一行看起来像 Fish Filet;Yummy fish in a sandwich.;9.95 和以此类推。

【讨论】:

    【解决方案2】:

    试试

    db.run('.import "C:/Users/path/to/csv/file.csv"'
          + 'INTO TABLE menuItems'
          + 'FIELDS TERMINATED BY ","'
          + 'ENCLOSED BY "\'"'
          + 'LINES TERMINATED BY \'\\n\''
          + 'IGNORE 1 ROWS'
          + ')');
    

    . 开头的命令结尾不需要分号

    【讨论】:

      【解决方案3】:

      我最终选择了选项 3。即,我使用 fs 包读取 CSV 文件,进行一些解析,在 Promise 对象中返回结果,并在 @987654324 中插入数据库@表示Promise对象。

      【讨论】:

      • 能分享一下实现的代码吗?我一直在这样做,但仍然出现错误..
      • 嗨@NikhilAgarwal,可以在私有here 函数中找到实现getCSV
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-19
      • 2020-08-23
      • 1970-01-01
      相关资源
      最近更新 更多