sql - 包含序列的重复 postgresql 模式

标签 sql postgresql database-schema multi-tenant

我的数据库布局需要为每个新客户创建新模式。目前我使用在网上找到的内部函数并稍微修改。

CREATE FUNCTION copy_schema(
    source_schema character varying, 
    target_schema character varying, 
    copy_data boolean)
RETURNS integer AS
$BODY$
DECLARE
    t_ex integer := 0;
    s_ex integer := 0;
    src_table character varying;
    trg_table character varying;
BEGIN
    if (select 1 from pg_namespace where nspname = source_schema) THEN
        -- we have defined target schema
        s_ex := 1;
    END IF;

    IF (s_ex = 0) THEN
        -- no source schema exist
        RETURN 0;
    END IF;

    if (select 1 from pg_namespace where nspname = target_schema) THEN
        -- we have defined target schema need to sync all table layout
        t_ex := 1;
    ELSE
        EXECUTE 'CREATE SCHEMA '||target_schema||' AUTHORIZATION user';
    END IF;

    FOR src_table IN 
       SELECT table_name 
       FROM information_schema.TABLES 
       WHERE table_schema = source_schema
    LOOP
        trg_table := target_schema||'.'||src_table;
        EXECUTE 
            'CREATE TABLE ' || trg_table || ' (LIKE ' || source_schema || '.' || src_table || ' INCLUDING ALL)';
        IF (copy_data = true) THEN
            EXECUTE 'INSERT INTO ' || trg_table || '(SELECT * FROM ' || source_schema || '.' || src_table || ')';
        END IF;
    END LOOP;

    return t_ex;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;

此脚本的问题是新模式中的表继续使用源模式的序列。有没有办法使用 sql 语句(或其他可靠的方法)为新创建的表获取序列的新副本(或者甚至是复制整个模式的另一种可靠方法)?

最佳答案

问题的根源

与旧序列的连接来自所涉及列的普通默认值。我引用 the manual here :

Default expressions for the copied column definitions will only be copied if INCLUDING DEFAULTS is specified. The default behavior is to exclude default expressions, resulting in the copied columns in the new table having null default.

由于您使用

创建了新表
INCLUDING ALL

和:

INCLUDING ALL is an abbreviated form of INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING INDEXES INCLUDING STORAGE INCLUDING COMMENTS.

.. 你得到相同的默认值。您可以在创建新表后排除默认值或显式更改默认值,包括 nextval()。我认为没有任何中间立场。


转储/破解转储/恢复更简单

or even another reliable way to duplicate entire schema

您可以使用 pg_dump 转储模式的模式(同一个词,不同的含义):

pg_dump $DB -p $PORT -n $SCHEMA -sf /var/lib/postgresql/your_name.pgsql

破解转储(意思是:在转储上使用文本编辑器,或编写脚本):交换转储顶部的架构名称,以及 SET search_path 中的所有其他事件,并作为架构-序列资格甚至更多。如果您为架构选择了一个唯一名称,则运行一次全局搜索并用您喜欢的工具(sedvim 或.. .) 应该完成这项工作。

然后使用 psql 对同一个或任何其他数据库运行 SQL 脚本:

psql $DB -p $PORT -f /var/lib/postgresql/your_name.pgsql > /dev/null

与我最初发布的内容相反,串行列在转储中仍然分开(至少在 PostgreSQL 9.1.5 中)。 SQL 脚本单独创建序列,将它们附加到序列列:

ALTER SEQUENCE seq OWNED BY tbl.col;

并单独设置默认值。

顺便说一句:当前版本的 pgAdmin 在满足所有要求时对 DDL 脚本中的 serial 列进行逆向工程。

关于sql - 包含序列的重复 postgresql 模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12572088/

相关文章:

SQL 查询基于当前日期的另一个日期时间列返回唯一日期?

c# - 优化日历应用程序的查询和/或数据模型

mysql - Web 统计表的数据库字段

mysql - sql中多个相互关联的循环

mysql - 我应该删除我的 MySQL 记录,还是应该有一个标志 "is_deleted"?

postgresql - PyQt,如何检查数字数组是否具有特定长度

postgresql - 让 Postgres 在必要时截断值?

ruby-on-rails - 搜索给定不同货币价格范围的型号

java - 从spring-data-jdbc的 "Entities"生成脚本sql

mysql - 完全加入不工作