加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

postgresql – 如何将Postgres外键模仿到分区表中

发布时间:2020-12-13 15:52:48 所属栏目:百科 来源:网络整理
导读:我有一个分区表(称之为A),其中一个串行主键由另一个表引用(称之为B).我知道我实际上不能从一个到另一个创建一个外键(因为我不知道数据实际存储在哪个分区),所以相反,我试图模仿外键的行为使用check限制.类似于以下内容: CREATE TABLE A ( MyKey SERIAL PRIM
我有一个分区表(称之为A),其中一个串行主键由另一个表引用(称之为B).我知道我实际上不能从一个到另一个创建一个外键(因为我不知道数据实际存储在哪个分区),所以相反,我试图模仿外键的行为使用check限制.类似于以下内容:

CREATE TABLE A (
    MyKey SERIAL PRIMARY KEY
);

CREATE TABLE B (
    AKey INT,-- Should have: REFERENCES A (MyKey),-- but can't due to Postgres limitations
);

CREATE TABLE APart1 (
    Field1 INT,PRIMARY KEY (MyKey)
) INHERITS (A);

CREATE TABLE APart2 (
    Field2 INT,PRIMARY KEY (MyKey)
) INHERITS (A);

CREATE FUNCTION ValidateKeyInA(aKey INT) RETURNS BOOL AS $$
    BEGIN
        PERFORM * FROM A WHERE MyKey = aKey;
        IF FOUND THEN
            RETURN TRUE;
        END IF;
        RETURN FALSE;
    END;
$$LANGUAGE PLPGSQL;

ALTER TABLE B ADD CHECK (ValidateKeyInA(AKey));

WITH aKey AS (INSERT INTO APart1 (Field1) VALUES (1) RETURNING MyKey)
INSERT INTO B (AKey) SELECT * FROM aKey;

WITH aKey AS (INSERT INTO APart2 (Field2) VALUES (2) RETURNING MyKey)
INSERT INTO B (AKey) SELECT * FROM aKey;

这很好用,直到我去转储和恢复数据库.那时,Postgres不知道表B依赖于表A(及其分区)中的数据,而B恰好在表A之前被转储.我试图将“DEFERRABLE”关键字添加到我所在的行添加约束,但Postgres不支持可延迟检查约束.

我建议的方法是将我的检查约束转换为约束触发器,我可以推迟,然后在事务中导入我的数据库转储.对此有更直接的方法吗?例如,有没有办法让我告诉Postgres不要转储表B,直到表A及其所有分区都被转储(例如,从B添加依赖关系到A的分区)?我应该使用的其他一些模式呢?谢谢.

解决方法

pg_dump按字母顺序自动排序表(参见上面的评论).但是,如果要更改转储和还原表的顺序,但无法根据所需顺序重命名表,则可以将–use-list选项与pg_restore一起使用.见 http://www.postgresql.org/docs/9.3/static/app-pgrestore.html

pg_restore允许控制顺序,如何使用选项–use-list恢复数据库元素.

您首先使用选项-Fc以自定义格式转储数据库,否则无法使用pg_restore恢复转储:

pg_dump -Fc your_database -f database.dump

比生成一个列出转储中所有元素的文件:

pg_restore --list database.dump > backup.txt

文件backup.txt将用作pg_restore选项–use-list的输入,但首先您可以编辑文件并使用复制/粘贴更改行的顺序.您可以独立更改表创建和数据插入.请注意您的列表保持一致.您还可以完全删除行,以便从还原中排除元素.

最后使用选项–use-list恢复转储:

pg_restore -d your_database --use-list backup.txt database.dump

我使用您的示例测试了此过程并更改了表A和B的顺序.如果首先还原表A,则会恢复转储而不会出现错误.否则,如果首先还原B,则还原将按预期失败,并显示错误:

pg_restore: [archiver (db)] COPY failed for table “b”: ERROR: new row for relation “b” violates check constraint “b_akey_check” DETAIL: Failing row contains (1). CONTEXT: COPY b,line 1: “1” WARNING: errors ignored on restore: 1

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读