【问题标题】:Shell script to execute pgsql commands in files用于在文件中执行 pgsql 命令的 Shell 脚本
【发布时间】:2011-12-21 18:41:26
【问题描述】:

我正在尝试自动化一组创建 TEMPLATE 数据库的过程。

我有一组文件(file1、file2、...fileN),每个文件都包含一组创建 TEMPLATE 数据库所需的 pgsql 命令。

文件(createdbtemplate1.sql)的内容大致如下:

CREATE DATABASE mytemplate1 WITH ENCODING 'UTF8';

\c mytemplate1

CREATE TABLE first_table ( 
 --- fields here ..
);

-- Add C language extension + functions
\i db_funcs.sql

我希望能够编写一个 shell 脚本来执行文件中的命令,这样我就可以编写这样的脚本:

# run commands to create TEMPLATE db mytemplate1
# ./groksqlcommands.sh createdbtemplate1.sql

for dbname in foo foofoo foobar barbar
do
    # Need to simply create a database based on an existing template in this script
    psql CREATE DATABASE $dbname TEMPLATE mytemplate1
done

关于如何做到这一点的任何建议? (你可能已经猜到了,我是一个 shell 脚本新手。)

编辑

为了进一步澄清这个问题,我想知道:

  1. 如何编写 groksqlcommands.sh(从文件运行一组 pgsql cmds 的 bash 脚本)
  2. 如何在命令行基于现有模板创建数据库

【问题讨论】:

  • 您的问题含糊不清。首先,您要使用多个文件创建模板数据库。但是随后您的代码示例尝试基于模板数据库创建多个数据库。你到底想做什么?
  • @ErwinBrandstetter:不完全是。我会尽力澄清。一个(sql 命令)文件包含一组文件来创建一个 SINGLE 模板数据库。 (sql 命令)文件和模板数据库之间存在 1:1 映射。我想创建一个自动创建数据库的 bash 脚本。创建的数据库是从之前在脚本中创建的模板数据库“派生的”。 bash 脚本根据运行时脚本变量创建不同的模板数据库(及其派生数据库)。 HTH。
  • 更正:一个(sql命令)文件包含一组SQL命令来创建一个SINGLE模板数据库。

标签: bash postgresql psql


【解决方案1】:

首先,不要混合使用psql 元命令和SQL 命令。这些是单独的命令集。有一些技巧可以将它们结合起来(使用 psql 元命令 \o\\ 并在 shell 中将字符串传递给 psql),但这很快就会让人困惑。

  • 使您的文件只包含 SQL 命令。
  • 不要在 SQL 文件中包含 CREATE DATABASE 语句。单独创建数据库,您有多个文件要在同一个模板数据库中执行。

假设您以操作系统用户 postgres 的身份进行操作,并将 DB 角色 postgres 用作(默认)Postgres 超级用户,所有数据库都在默认端口 5432 上的同一个数据库集群中,并且由于pg_hba.conf 中的IDENT 设置(默认设置),角色postgres 具有无密码访问权限。

psql postgres -c "CREATE DATABASE mytemplate1 WITH ENCODING 'UTF8'
                  TEMPLATE template0"

我的新模板数据库基于默认系统模板数据库template0Basics in the manual here.

您的问题

如何(...)从文件中运行一组 pgsql cmds

试试:

psql mytemplate1 -f file

目录中批量文件的示例脚本文件:

#! /bin/sh

for file in /path/to/files/*; do
    psql mytemplate1 -f "$file"
done

命令选项-f 使psql 在文件中执行SQL 命令。

如何在命令行基于现有模板创建数据库

psql -c 'CREATE DATABASE my_db TEMPLATE mytemplate1'

命令选项-c 使psql 执行单个SQL 命令字符串。可以是多个命令,由; 终止 - 将在一个事务中执行,并且只返回最后一个命令的结果。
阅读psql command options in the manual

如果您不提供要连接的数据库,psql 将连接到名为“postgres”的默认维护数据库。在第二个答案中,我们连接到哪个数据库无关紧要。

【讨论】:

    【解决方案2】:

    你可以echo你的命令到psql输入:

    for dbname in foo foofoo foobar barbar
    do
        echo """
    CREATE DATABASE $dbname TEMPLATE mytemplate1
    """ | psql
    done
    

    【讨论】:

    • 我猜你的答案与我的问题的第二部分有关(顺便说一句,psql 不会像你写的那样提示输入用户名和密码吗?)。从上面看不清楚,如何在文件中执行单个命令(除非您建议读取文件中的行,遍历这些行并回显到 psql?)
    • echo 中的内容与 psql 提示符中的正常输入中的内容相同,因此您可以执行 \i file_with_commands.sql 来执行整个文件,或者您可以使用 sed 创建过滤器然后通过它的输出到 psql,比如echo "CREATE DATABASE __dbname__" | sed "s/__db_name/$variable_with_db_name/g" | psql。至于 psql 要求密码,这取决于您的 PostgresSQL 配置,但如果您不想配置没有密码的用户,您仍然可以手动输入密码。
    【解决方案3】:

    如果您愿意加倍努力,sqlalchemy 可能会取得更大的成功。它将允许您使用 python 而不是 bash 构建脚本,这更容易并且具有更好的控制。

    根据 cmets 的要求:https://github.com/srathbun/sqlCmd

    【讨论】:

    • 嗯,你可能正在那里。事实上,我刚刚(今天!)开始使用 sqlalchemy ......但是学习曲线陡峭,我认为使用 bash 会更容易/更快。
    • @HomunculusReticulli 哦,使用 bash 绝对更容易。但是,任何有用的东西都会被重复使用,所有那些你告诉自己的边缘不会出现在你的一次性脚本中,会回来咬你。
    • @HomunculusReticulli 巧合的是,我创建了一些非常相似的东西,尽管数据库是一个 mssql 实例,而且我还有一些其他要求。我花了一个月的大部分时间,有些地方我希望我做得不同。但大多数情况下,我希望我使用 sqlalchemy。如果您有兴趣,我可以将代码上传到 github,供您阅读。
    • 我同意 bash 方法虽然(表面上)现在更快,但可能会在稍后阶段回来咬我。我更喜欢 sqlAlchemy 方法 - 特别是如果我有一个起点可以工作。看看你以前做过什么会很有帮助。请将您的代码上传到 github,这样我可以看看它是否可以给我一些关于使用 sqlalchemy 的想法。谢谢
    • @HomunculusReticulli 我添加了一个指向 github 存储库的链接。请注意,我是为 我的 需要而构建的。由于是 sql 和额外的命令,它有一些限制,就像所有的迷你语言一样。也就是说,它适合我的问题集,没有其他人的。
    【解决方案4】:

    将您的 sql 脚本存储在根目录下 使用 dev,tst,prd 参数化 dbs 使用 find 运行所有 pgsql 脚本,如 here 所示 错误退出

    或者只是从here git clone 整个工具

    【讨论】:

      【解决方案5】:

      对于你必须这样做的用例......

      这是我用于将 JSON 导入 PostgreSQL(WSL Ubuntu)的脚本,它基本上要求您在同一命令行中混合 psql 元命令和 SQL。注意使用有点晦涩的脚本命令,它分配一个伪终端:

      $ more update.sh
      #!/bin/bash
      wget <filename>.json
      echo '\set content `cat $(ls -t <redacted>.json.* | head -1)` \\ delete from <rable>; insert into <table> values(:'"'content'); refresh materialized view <view>; " | PGPASSWORD=<passwd> psql -h <host> -U <user> -d <database>
      $ 
      

      【讨论】:

        猜你喜欢
        • 2013-09-22
        • 2012-12-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-26
        • 1970-01-01
        • 2017-01-13
        相关资源
        最近更新 更多