【问题标题】:I want to restore the database with a different schema我想用不同的模式恢复数据库
【发布时间】:2010-11-16 06:20:18
【问题描述】:

我使用以下命令转储了一个名为 temp1 的数据库

$  pg_dump -i -h localhost  -U postgres -F c -b -v -f pub.backup temp1 

现在我想在另一个名为“db_temp”的数据库中恢复转储,但我只想在“temp_schema”中创建所有表(而不是 fms temp1 数据库中的默认模式)这是在“db_temp”数据库​​中。

有没有办法使用pg_restore 命令来做到这一点?

任何其他方法也值得赞赏!

【问题讨论】:

  • 我无法接受这种情况在 2017 年仍然发生,解决方案是破解转储文件。
  • 2018 我的朋友!
  • 您可以使用 DBeaver 将其导出到另一个架构中。一口气!
  • 2020 我的朋友! @user1880957 问题是关于自动内置方式,而不是依赖于某些 GUI 工具的手动方式
  • 2021 现在该死的 x)

标签: postgresql pg-dump pg-restore


【解决方案1】:

一种快速而肮脏的方式:

1) 重命名默认架构:

alter schema public rename to public_save;

2) 创建新模式作为默认模式:

create schema public;

3) 恢复数据

pg_restore -f pub.backup db_temp [and whatever other options]

4) 根据需要重命名模式:

alter schema public rename to temp_schema;
alter schema public_save rename to public;

【讨论】:

    【解决方案2】:

    有一个简单的解决方案:

    • 以纯 SQL 格式创建备份转储(格式“p”,使用参数 --format=p-F p
    • 使用您喜欢的编辑器编辑您的 pub.backup.sql 转储,并在文件顶部添加以下两行:

    create schema myschema;

    SET search_path TO myschema;

    现在您可以使用命令恢复备份转储

    psql -f pub.backup.sql

    set search_path to <schema> 命令会将 myschema 设置为默认值,以便在此架构中创建新表和其他对象,而与它们之前所在的“默认”架构无关。

    【讨论】:

    • 有没有一种巧妙的方法来实际只编辑大型转储文件的头部?即使是这样的事情也涉及复制它:superuser.com/questions/246837/…
    • @PeterEhrlich 根据您的文件大小和可用 RAM,您可以使用 vim 直接打开 gzip 转储文件。它仍然在内存中扩展,但我能够打开、编辑和保存一个 750MB (.gz) 文件,在保存时只需要短暂的暂停。 YMMV。
    • @PeterEhrlich 您可以使用子进程在转储内容之前将某些内容写入文件。例如:( echo "CREATE SCHEMA myschema; SET search_path TO myschema;" ; pg_dump -F p ... ) | gzip -9 > dump.sql.gz
    • @gldnspud 但据我了解,这仅意味着文件中有 2 个“SET search_path”?第二个是我们不想要的。
    • 这在 Postgres 9.6.8 / 10.3 中不起作用:pg_dump 不再使用 SET search_path;相反,它将模式名称作为转储中所有命令的前缀
    【解决方案3】:

    pg_restore 本身没有办法。您可以做的是使用 pg_restore 生成 SQL 输出,然后通过例如 sed 脚本发送它来更改它。不过,您需要小心编写该 sed 脚本的方式,以免它不匹配并更改数据中的内容。

    【讨论】:

      【解决方案4】:

      可能最简单的方法是在恢复后简单地重命名架构,即使用以下 SQL:

      ALTER SCHEMA my_schema RENAME TO temp_schema
      

      我相信,因为您使用压缩存档格式作为 pg_dump 的输出,所以您无法在恢复之前对其进行更改。选项是使用默认输出并在架构名称上进行搜索和替换,但这样做有风险,如果您不小心,可能会导致数据损坏。

      【讨论】:

      • 这个解决方案会弄得一团糟是不是
      • 以什么方式?? SQL 语句是更改模式名称的唯一安全方法。在另一个答案中也提出了另一种解决方案,我们都解释说它是有风险的。差评。
      • 我更改了架构名称,但之后,我无法更改搜索路径!重命名后用户无法搜索任何表!
      【解决方案5】:

      如果您只有几个表,那么您可以一次恢复一个表,pg_restore 在您指定 -t tablename 时接受 -d database。当然,您必须在恢复表之前设置架构,然后在完成恢复表时整理索引和约束。

      或者,在不同的端口上设置另一台服务器,使用新的 PostgreSQL 服务器恢复,重命名架构,转储它,然后恢复到原始数据库。这当然有点杂乱无章,但它会完成工作。

      如果您喜欢冒险,您也许可以使用十六进制编辑器更改转储文件中的数据库名称。我认为它只在转储中的一个地方提到,只要新旧数据库名称相同,它就可以工作。 YMMV,不要在生产环境中做这样的事情,如果这炸毁了你的家乡,不要怪我,以及所有其他常见的免责声明。

      【讨论】:

        【解决方案6】:

        重命名临时数据库中的架构。

        导出架构:

        pg_dump --schema-only --schema=prod > prod.sql
        

        创建一个新数据库。恢复导出:

        psql -f prod.sql
        
        ALTER SCHEMA prod RENAME TO somethingelse;
        
        pg_dump --schema-only --schema=somethingelse > somethingelse.sql
        

        (删除数据库)

        对于数据,您只需修改顶部的集合search_path

        【讨论】:

          【解决方案7】:

          如前所述,pg_dump、psql 或 pg_restore 不直接支持在转储/恢复过程中更改模式名称。但是使用“普通”格式导出然后修改 .sql 文件相当简单。这个 Bash 脚本执行以下基本操作:

          rename_schema () {
          
            # Change search path so by default everything will go into the specified schema
            perl -pi -e "s/SET search_path = $2, pg_catalog/SET search_path = $3, pg_catalog, $2;/" "$1"
          
            # Change 'ALTER FUNCTION foo.' to 'ALTER FUNCTION bar.'
            perl -pi -e 's/^([A-Z]+ [A-Z]+) '$2'\./$1 '$3'./' "$1"
          
            # Change the final GRANT ALL ON SCHEMA foo TO PUBLIC
            perl -pi -e 's/SCHEMA '$2'/SCHEMA '$3'/' "$1"
          
          }
          

          用法:

          pg_dump --format plain --schema=foo --file dump.sql MYDB
          rename_schema dump.sql foo bar
          psql -d MYDB -c 'CREATE SCHEMA bar;'
          psql -d MYDB -f dumpsql
          

          【讨论】:

          • (大家:请随时更新此答案以改进 Bash。)
          • 我会使用 sed "s/\b$OLD_SCHEMA/$NEW_SCHEMA/g"
          • 如其他答案之一所述,如果架构名称存在于其他地方(例如数据中),则需要小心。他的 perl 脚本比简单地替换所有 $OLD_SCHEMA 的出现要安全一些。
          【解决方案8】:

          这个问题很老了,但也许可以帮助一些人。

          pg_restore 的输出流式传输到sed 并替换架构名称,以便将转储导入不同的架构。

          类似:

          pg_restore ${dumpfile} | \
              sed -e "s/OWNER TO ${source_owner}/OWNER TO ${target_owner}/" \
                  -e "s/${source_schema}/${target_schema}/" | \
                 psql -h ${pgserver} -d ${dbname} -U ${pguser} 
          

          【讨论】:

          • 您的意思是 pg_dump 是与 pg_restore 相对的第一个命令?
          • @JohnSmith 不,我的意思是 pg_restore。您应该进行转储,然后在目标数据库上导入转储时执行替换架构。
          • @Dwhitz 有小错字;它应该是 {"source_schema"/"target_schema"/}
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-01-24
          相关资源
          最近更新 更多