[英]Import sql file in node.js and execute against PostgreSQL
我正在尋找一種有效的方法來獲取原始 sql 文件並讓它針對 postgres 數據庫同步執行,類似於通過psql
運行它。
我有一個 sql 文件,它創建所有數據庫、導入數據等。我需要使用 node.js 執行它,但找不到任何自動執行此操作的模塊。 對於 node.js 應用程序本身,我們使用 node-postgres ('pg')、knex.js 和 bookshelf.js。 我認為 pg 最適合這個。
我能想到的一種替代方法是讀取整個文件,用分號分割,用空格替換換行符,修剪任何重復的空格,然后以順序執行而不是異步執行的方式將其一個一個地輸入 pg。 如果這真的是最有效的方法,並且還沒有庫來解決這個問題,我有點驚訝。 我有點猶豫要不要跳進去,因為 SQL 語法本身就有點挑戰性,我可能會不小心把它混搭。
提前說明幾點:
psql
不能使用,因為它沒有安裝在目標機器上傳遞給client.query
時,您可以使用分號分隔后續查詢
那個有效:
var pg = require('pg');
pg.connect('postgres://test:test@localhost/test', function(err, client, done){
client.query('CREATE TABLE test (test VARCHAR(255)); INSERT INTO test VALUES(\'test\') ');
done();
});
因此,這也有效:
var pg = require('pg');
var fs = require('fs');
var sql = fs.readFileSync('init_database.sql').toString();
pg.connect('postgres://test:test@localhost/test', function(err, client, done){
if(err){
console.log('error: ', err);
process.exit(1);
}
client.query(sql, function(err, result){
done();
if(err){
console.log('error: ', err);
process.exit(1);
}
process.exit(0);
});
});
我編寫了以下適用於我的案例的函數。 如果不是因為:
batch
來管理並發代碼片段:
function processSQLFile(fileName) {
// Extract SQL queries from files. Assumes no ';' in the fileNames
var queries = fs.readFileSync(fileName).toString()
.replace(/(\r\n|\n|\r)/gm," ") // remove newlines
.replace(/\s+/g, ' ') // excess white space
.split(";") // split into all statements
.map(Function.prototype.call, String.prototype.trim)
.filter(function(el) {return el.length != 0}); // remove any empty ones
// Execute each SQL query sequentially
queries.forEach(function(query) {
batch.push(function(done) {
if (query.indexOf("COPY") === 0) { // COPY - needs special treatment
var regexp = /COPY\ (.*)\ FROM\ (.*)\ DELIMITERS/gmi;
var matches = regexp.exec(query);
var table = matches[1];
var fileName = matches[2];
var copyString = "COPY " + table + " FROM STDIN DELIMITERS ',' CSV HEADER";
var stream = client.copyFrom(copyString);
stream.on('close', function () {
done();
});
var csvFile = __dirname + '/' + fileName;
var str = fs.readFileSync(csvFile);
stream.write(str);
stream.end();
} else { // Other queries don't need special treatment
client.query(query, function(result) {
done();
});
}
});
});
}
請注意,如果您在除終止 SQL 語句之外的任何地方使用分號,這都會失敗。
@databases/pg
客戶端支持開箱即用的運行 SQL 文件:
const createPool = require('@databases/pg');
const {sql} = require('@databases/pg');
const db = createPool();
db.query(sql.file('my-file.sql')).catch(ex => {
console.error(ex);
process.exitCode = 1;
}).then(() => db.dispose());
它還支持在一次調用db.query
中包含多個語句:
const createPool = require('@databases/pg');
const {sql} = require('@databases/pg');
const db = createPool();
db.query(sql`
INSERT INTO users (name) VALUES (${'Forbes'});
SELECT * FROM users;
`)).then(
results => console.log(results)
).catch(ex => {
console.error(ex);
process.exitCode = 1;
}).then(() => db.dispose());
本例中,每條語句依次運行,返回最后一條語句的結果。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.