【问题标题】:Creating a Database programmatically with node-postgres使用 node-postgres 以编程方式创建数据库
【发布时间】:2021-01-13 04:38:57
【问题描述】:

我想在用户启动应用程序时创建一个数据库(如果该应用程序尚不存在)。我尝试这样做的方法是,因为我不知道在没有现有连接的情况下创建数据库的方法是连接到标准的 postgres 数据库,这是一个默认的预先存在的数据库(我认为)。

连接后,我会从默认连接执行此操作:

`SELECT 'CREATE DATABASE dbName WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'dbName')\\gexec`

如果数据库不存在,这可能会创建数据库。一旦运行,我保证有一个存在的 dbName 数据库。因此,我关闭了另一个连接,因为它不再需要

postgresCon.end();

我连接到最近创建的数据库,希望随后可以使用它来执行我想要的任何查询,并让用户能够添加锻炼/锻炼/其他任何内容。

问题 每当我运行Select create database exercise... 语句时,我都会发现错误,它给我的是“错误:连接终止”,可以肯定地说这个错误并不是真的......描述性的。事实上,当锻炼数据库已经存在时,就会发生这种情况。如果不存在,它只会抱怨(稍后 - 当我尝试在此数据库上执行查询时)它不存在。

这是代码,我的理论是它是异步的,因此虽然连接“开始连接”,但其余查询已经在运行并返回“不存在”,因为它还没有完全尚未创建。

这里是 pastebin 上一些突出显示的代码(虽然显然它对 '' 不满意,所以突出显示可能有点磨损):https://pastebin.com/fiiK35j7

如果您需要更多细节/代码/更清晰,请询问!

编辑有人告诉我我的理论是正确的,我应该使用 async/await,但我不确定如何在连接成功完成之前停止运行查询,我认为它必须是这样的:

async connection() => {await db.connect()}

connection()
.then(can do queries here)
.catch(panic)

但我不确定什么会真正起作用

【问题讨论】:

  • 这听起来是个非常糟糕的主意,因为这意味着您的 Node 应用程序正在连接为超级用户,这是一个巨大的安全风险。创建数据库应该是数据库服务器设置过程的一部分,而不是允许应用程序做的事情。

标签: node.js postgresql


【解决方案1】:

我不相信您可以从应用程序代码中调用\gexec。这是一个只能从psql cli 工具中使用的命令。

您必须发出和查询,然后在应用程序代码中执行条件,以便随后创建(或不创建)数据库。

如上所述,从应用程序连接数据库超级用户是个坏主意。但是在某些情况下可能需要这样做,即从 CI/CD 管道中,如果新环境中不存在数据库和用户,您希望在其中配置它们。我做了以下事情(使用 ts-postgres 而不是 node-postgres):

const [host, username, password] = ['localhost', 'user', 'pass']
const client = new Client({host, user: username, password})
await client.connect()

///// 
// There is no CREATE DATABASE IF NOT EXISTS in postgres, which is decidedly annoying
// instead, we have to query and see if the database and user exists, and if not, create them
const dbQuery = await client.query(`SELECT FROM pg_database WHERE datname = $1`, [applicationDatabaseName])
if (dbQuery.rows.length === 0)  {
    // database does not exist, make it:
    await client.query(`CREATE DATABASE ${applicationDatabaseName}`)
}


const userQuery = await client.query(`SELECT FROM pg_roles where rolname = $1`, [applicationDatabaseUser])
if(userQuery.rows.length === 0) {
    //user doesn't exist. make it
    await client.query(`CREATE USER ${applicationDatabaseUser} with ENCRYPTED PASSWORD '${applicationDatabasePassword}'`)
    await client.query(`GRANT ALL PRIVILEGES ON DATABASE ${applicationDatabaseName} TO ${applicationDatabaseUser}`)
}
await client.end()

【讨论】:

    猜你喜欢
    • 2014-01-15
    • 1970-01-01
    • 2019-08-10
    • 1970-01-01
    • 2021-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多