Использование файла CSV в пакете node-sqlite3
Я использую нпм 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
файл. Есть несколько решений, о которых я могу подумать:
Используйте текущую реализацию и команды с жестким кодом для вставки отдельных элементов в таблицу.
Используйте SQLite3 для импорта
csv
файл и вставьте его в таблицу.*Читать в пунктах от
csv
файл и вставьте их через цикл.Создайте базу данных до запуска сервера и передайте ее в
sqlite3.Database()
конструктор.
* Я хотел бы перейти к варианту 2. Однако, так как это для целей обучения, я открыт для любых предложений, включая, но не ограничиваясь, использование другого пакета управления базой данных или использование другого типа файла (может быть, просто txt
файл или что-то).
Я знаю, что есть несколько способов импортировать csv
файл с использованием SQLite3. Я пытаюсь сделать то же самое, но из 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
Пытаясь использовать нормальный синтаксис SQL,
.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, похоже, сработает, но я еще не пробовал.
4 ответа
Я закончил с вариантом 3. А именно, я использовал fs
пакет для чтения в CSV-файле, сделал некоторый анализ, вернул результаты в течение Promise
объект, и сделал вставки базы данных в пределах then
из сказанного Promise
объект.
Есть небольшой пример для чтения вашего 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;Вкусная рыба в бутерброде.;9,95 и так далее.
Пытаться
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'
+ ')');
команды, начинающиеся с .
не нужно ставить точку с запятой в конце
например, создайте файл file.csv, заголовок — это имена столбцов, строки — это записи, разделенные ; и строки в формате «строка» :
itemName;itemDescription;unitPrice
"Рыбное филе";"Вкусная рыбка в бутерброде.";9,95
2.1 Если типы столбцов не так важны, вы можете импортировать файл csv в базу данных с помощью file.sql3:
.mode csv
.separator ";"
drop table if exists menuItems;
.import "file.csv" menuItems
2.2 запускаем импорт из nodejs:
const { exec } = require('node:child_process');
exec('sqlite3 "memory.db" < "file.sql3"', (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
});
3.1 Если типы столбцов важны, вы можете импортировать файл csv в базу данных во временную таблицу tmp с помощью этого tmp.sql3 :
.mode csv
.separator ";"
drop table if exists tmp;
.import "file.csv" tmp
3.2 запускаем импорт из nodejs:
const { exec } = require('node:child_process');
const sql3 = require('better-sqlite3');
exec('sqlite3 "memory.db" < "tmp.sql3"', (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
const db = new sql3('memory.db');
db.exec( "CREATE TABLE IF NOT EXISTS menuItems(" +
+ 'itemName VARCHAR(255),'
+ 'itemDescription VARCHAR(255),'
+ 'unitPrice REAL'
+ ');');
db.exec("INSERT INTO menuItems " +
+ "select itemName, itemDescription, unitPrice from tmp;");
});