Javascript 在node.js中导入sql文件并对PostgreSQL执行
我正在寻找一种有效的方法来获取原始sql文件并对postgres数据库同步执行它,类似于通过Javascript 在node.js中导入sql文件并对PostgreSQL执行,javascript,sql,node.js,postgresql,node-postgres,Javascript,Sql,Node.js,Postgresql,Node Postgres,我正在寻找一种有效的方法来获取原始sql文件并对postgres数据库同步执行它,类似于通过psql运行它 我有一个创建所有数据库、导入数据等的sql文件。我需要使用node.js执行此操作,但找不到任何自动执行此操作的模块。对于node.js应用程序本身,我们使用node postgres('pg')、knex.js和bookshelf.js。我想pg是最好的选择 我能想到的另一种方法是读取完整文件,用分号分割,用空格替换换行符,修剪任何重复的空格,然后以顺序而不是异步执行的方式将其逐个送入p
psql
运行它
我有一个创建所有数据库、导入数据等的sql文件。我需要使用node.js执行此操作,但找不到任何自动执行此操作的模块。对于node.js应用程序本身,我们使用node postgres('pg')、knex.js和bookshelf.js。我想pg是最好的选择
我能想到的另一种方法是读取完整文件,用分号分割,用空格替换换行符,修剪任何重复的空格,然后以顺序而不是异步执行的方式将其逐个送入pg。如果这真的是最有效的方法,而且还没有库可以解决这个问题,我有点惊讶。我有点犹豫要不要跳进去,因为SQL语法本身可能有点挑战性,我可能会不小心把它搞乱
事先作出一些澄清:
无法使用,因为它未安装在目标计算机上psql
- 我选择以sql本机形式开发和控制sql语句,因为DBA使用和操作它要容易得多
- 使用批处理来管理并发性
- 考虑棘手的PostgreSQL复制案例
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语句,则此操作都会失败。在传递到
客户端时,您可以用分号分隔后续查询。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);
});
});
客户端支持开箱即用地运行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());
在本例中,每个语句都按顺序运行,并返回最后一个语句的结果。这比您最初想象的要困难,因为您需要在SQL中区分文本和关键字。举一个简单的例子,用分号拆分不能处理insert-into-table值(“;”)代码>我最初尝试过,但发现了一些问题:*SQL文件中传统的换行符和制表符无法填充到client.query中,(通过一些额外的步骤可以解决)*每个查询的错误处理都非常困难(我承认我在这里的示例中也没有提到这一点)@rgareth我对SQL文件中的换行符和制表符完全没有任何问题。您可以将一些\n
s(甚至\r\n
s)和\t
s添加到我的示例中,它仍然可以工作。这对我的ibm\u db lib很有效。我也面临着同样的问题,但我想到了一个问题。关于SQL注入呢?您可以添加关于什么是批处理
的详细信息吗?关于导入带有函数的脚本呢?虽然您的回答对我有所帮助,但您可以提到@数据库
包是由您创建的:smiley:…此外,文档(在您的网站上)还可以改进,以包含更多示例,例如,我(作为Node JS新手)很难找到放置连接选项的位置,因为您的所有示例都在createConnectionPool()
中使用单个字符串,但是,我可以在其中放置一个具有支持的连接选项的对象。继续努力!感谢@Tukusejsirs的反馈如果您对文档有改进建议,我希望您能在PR提交。您需要编辑的所有文件都在这里: