如何阻止 Go gorm 在 Postgres 中对我的自引用外键强制非空约束

Posted

技术标签:

【中文标题】如何阻止 Go gorm 在 Postgres 中对我的自引用外键强制非空约束【英文标题】:How to stop Go gorm from forcing a not null constraint on my self referencing foreign key in Postgres 【发布时间】:2020-11-13 21:04:21 【问题描述】:

我需要创建一个在 gorm 中引用自身的表,但无法弄清楚为什么它会强制对我施加 not null 约束。我完全被难住了。我怎样才能解决这个问题?我正在使用 gorm 提供的 AutoMigrate 功能来创建表。在我删除外键约束的那一刻,not null 约束消失了,但这不是我想要的。

已编辑:我正在使用包“gorm.io/gorm”,而不是 Github 上的包。这也是唯一给我带来问题的表,任何其他具有引用其他表的外键的表都可以按预期工作。

使用外键

type User struct 
    ID *int `gorm:"primaryKey; type:serial"`
    Username string `gorm:"type: varchar(32) not null unique"`
    Password string `gorm:"type: varchar(128) not null"`
    ReferredBy *int
    Referrer *User `gorm:"foreignKey:ReferredBy;constraint:OnUpdate:CASCADE,ONDELETE:SET NULL"`

根据 pgAdmin 使用外键生成 SQL

-- Table: public.users

-- DROP TABLE public.users;

CREATE TABLE public.users
(
    id integer NOT NULL DEFAULT nextval('users_id_seq'::regclass),
    username character varying(32) COLLATE pg_catalog."default" NOT NULL,
    password character varying(128) COLLATE pg_catalog."default" NOT NULL,
    referred_by integer NOT NULL DEFAULT nextval('users_referred_by_seq'::regclass),
    CONSTRAINT users_pkey PRIMARY KEY (id),
    CONSTRAINT users_username_key UNIQUE (username),
    CONSTRAINT fk_users_referrer FOREIGN KEY (referred_by)
        REFERENCES public.users (id) MATCH SIMPLE
        ON UPDATE CASCADE
        ON DELETE SET NULL
)

TABLESPACE pg_default;

ALTER TABLE public.users
    OWNER to msmf;

不用外键

// User Model. ReferredBy is self referencing Foreign Key
type User struct 
    ID *int `gorm:"primaryKey; type:serial"`
    Username string `gorm:"type: varchar(32) not null unique"`
    Password string `gorm:"type: varchar(128) not null"`
    ReferredBy *int

结果 SQL 没有告诉 gorm 有外键

-- Table: public.users

-- DROP TABLE public.users;

CREATE TABLE public.users
(
    id integer NOT NULL DEFAULT nextval('users_id_seq'::regclass),
    username character varying(32) COLLATE pg_catalog."default" NOT NULL,
    password character varying(128) COLLATE pg_catalog."default" NOT NULL,
    referred_by bigint,
    CONSTRAINT users_pkey PRIMARY KEY (id),
    CONSTRAINT users_username_key UNIQUE (username)
)

TABLESPACE pg_default;

ALTER TABLE public.users
    OWNER to msmf;

【问题讨论】:

只有在自引用时才这样做吗? 是的,这是我唯一遇到问题的表。任何其他使用外键的表都可以。 对我来说听起来像是一个错误。 对我来说似乎也是一个,但我想先在这里检查一下,然后再在他们的 GitHub 上提出问题 【参考方案1】:

显然type:serial 标签可以做到这一点。如果你放弃它,非空约束也不会存在:

type User struct 
    ID       uint   `gorm:"primarykey"`
    Username string `gorm:"type: varchar(32) not null unique"`
    Password string `gorm:"type: varchar(128) not null"`
    ReferredBy *int
    Referrer   *User `gorm:"foreignKey:ReferredBy;constraint:OnUpdate:CASCADE,ONDELETE:SET NULL;"`

Reference github issue.

【讨论】:

以上是关于如何阻止 Go gorm 在 Postgres 中对我的自引用外键强制非空约束的主要内容,如果未能解决你的问题,请参考以下文章

gorm / go 如何正确连接两个表?

go-zero我是如何把gorm整合进go-zero的?

go-zero我是如何把gorm整合进go-zero的?

Go GORM 有很多关系。如何将数据存储到MYSQL DB

AWS RDS Postgres、GORM 和瞬态错误

Go语言使用gorm对MySQL进行性能测试