node-postgres 创建数据库
Posted
技术标签:
【中文标题】node-postgres 创建数据库【英文标题】:node-postgres create database 【发布时间】:2014-01-15 18:44:53 【问题描述】:我正在使用node-postgres,在我的应用程序开始时,我想检查数据库是否存在。所以我的工作流程思路如下:
-
检查
myDb
是否存在
如果存在,则创建表
如果没有,则先创建数据库,然后创建表
正如您所见,这是一个非常简单的过程,但是,驱动程序实现需要有一个数据库名称postgres://username:password@host/database
才能连接,这意味着您需要先连接到数据库。
所以我现在正在做的是在开始时连接到postgres
数据库,进行查询以创建数据库,如果它已经存在则捕获异常,然后关闭我的连接并连接到新创建的数据库,然后创建表。代码如下:
var conStringPri = 'postgres://' + username + ':' + password + '@' + host +
'/postgres';
var conStringPost = 'postgres://' + username + ':' + password + '@' + host +
'/' + dbName;
pg.connect(conStringPri, function(err, client, done) // connect to postgres db
if (err)
console.log('Error while connecting: ' + err);
client.query('CREATE DATABASE ' + dbName, function(err) // create user's db
if (err)
console.log('ignoring the error'); // ignore if the db is there
client.end(); // close the connection
// create a new connection to the new db
pg.connect(conStringPost, function(err, clientOrg, done)
// create the table
clientOrg.query('CREATE TABLE IF NOT EXISTS ' + tableName + ' ' +
'(...some sql...)';
);
);
);
如您所见,我打开和关闭了两次连接,这种方式对我来说似乎是错误的。如果您提出更好的方法,我会很高兴,或者解释一下您是如何做到的。
【问题讨论】:
据我所知,没有命令可以切换您连接到的数据库(在 psql 中有\c nameOfOtherDb
但这是 psql 中创建新连接并关闭旧连接的命令)。
另一种技术:您可以使用查询来查看它是否来自一个连接(来自“管理”连接):select count(*) from pg_catalog.pg_database where datname = 'the_db_name_here';
,然后创建/打开第二个连接。如果您连接到 2 个数据库,这似乎不是问题。
获取可用的数据库并检查我的数据库是否存在将创建一个 if/else,这将破坏我的同步回调。这就是我最终创建数据库并捕获异常的原因
在// ignore if the db is there
的行中,您忽略了所有错误。要忽略重复的数据库错误,您可以执行if (err && err.code === '42P04') console.log('ignoring the error'); else if (err) throw err;
之类的操作
【参考方案1】:
正如您所见,这是一个非常简单的过程,但是,驱动程序 实现需要有一个数据库名称 postgres://username:password@host/database 要连接,其中 意味着您需要先连接到数据库。
这不是因为驱动程序的实现,而是 PostgreSQL 本身。任何其他语言或驱动程序都一样。
客户端需要连接到数据库才能执行任何操作,包括CREATE DATABASE
。除了postgres
数据库,template1
也经常用于此目的。
然后,由于您必须连接到新创建的数据库才能在其中创建对象,因此无法避免打开另一个连接。
简而言之,你正在做的事情无法简化,它已经是最优的了。
【讨论】:
【参考方案2】:我刚刚为此编写了一个模块:https://github.com/olalonde/pgtools
var pgtools = require('pgtools');
pgtools.createdb(
user: 'postgres',
password: 'some pass',
port: 5432,
host: 'localhost'
, 'test-db', function (err, res)
if (err)
console.error(err);
process.exit(-1);
console.log(res);
);
希望它能让你的代码更简洁。
【讨论】:
【参考方案3】:这有点老了,但我只是想分享一下我是如何处理这种设置的。
您需要从回调中调用第三个参数,即来自pg.connect(conn, (err, client, done) => )
的done
。这将释放连接并恢复池。
async.series([
done =>
pg.connect(connPrimary, (err, client, releaseConn) =>
if (err) return done(err)
client.query(`CREATE DATABASE $conf.database`, (err) =>
if (err && !~err.message.indexOf('already exists'))
return done(err)
client.end()
releaseConn()
done()
)
)
,
done =>
let connSecondary = `postgres://$conf.user:$conf.password@$conf.host:$conf.port/$conf.database`
pg.connect(connSecondary, (err, client, releaseConn) =>
if (err) return done(err)
let createTableQuery = `CREATE TABLE IF NOT EXISTS test_table(_id bigint primary key, co2_field varchar(40) NOT NULL, temp_field int NOT NULL, quality_field decimal NOT NULL, reading_time_field timestamp NULL)`
client.query(createTableQuery, err =>
if (err) return done(err)
releaseConn()
done()
)
)
], err =>
should.ifError(err)
doneInit()
)
【讨论】:
【参考方案4】:安装
npm install --save -g pgtools
CLI 示例
createdbjs my_awesome_db --user=admin --password=admin
【讨论】:
【参考方案5】:这是我使用的一个脚本,它基本上只是用 execa 执行 shell 命令:
import execa from 'execa';
class DatabaseService
public async setupDatabase()
const logCmd = (cmd: execa.ExecaChildProcess) =>
cmd.stdout.on('data', (data) =>
this.logger.log(data.toString());
);
cmd.stderr.on('data', (data) =>
this.logger.error(data.toString());
);
;
const createUser = () =>
return new Promise<void>((resolve, reject) =>
const cmd = execa('createuser', [Config.databaseUser, '--superuser']);
logCmd(cmd);
let userExists = false;
cmd.stderr.on('data', (data) =>
if (
data
.toString()
.includes(`role "$Config.databaseUser" already exists`)
)
userExists = true;
);
cmd.on('exit', (code) =>
if (!userExists && code)
reject(new Error(`Failed to create user for database: $code`));
else
resolve();
);
);
;
const createDatabase = () =>
return new Promise<void>((resolve, reject) =>
const cmd = execa('createdb', [Config.databaseName]);
logCmd(cmd);
let databaseExists = false;
cmd.stderr.on('data', (data) =>
if (
data
.toString()
.includes(`database "$Config.databaseName" already exists`)
)
databaseExists = true;
);
cmd.on('exit', (code) =>
if (!databaseExists && code)
reject(new Error(`Failed to create database: $code`));
else
resolve();
);
);
;
await createUser();
await createDatabase();
如您所见,脚本会检测用户或数据库是否已经存在,并将忽略这些事件中的错误,因为 Postgres 的预期状态已经满足,而这就是我运行它时所关心的全部。
【讨论】:
以上是关于node-postgres 创建数据库的主要内容,如果未能解决你的问题,请参考以下文章