Java Flyway和PostgreSQL可空外键定义仍然生成非空约束

Java Flyway和PostgreSQL可空外键定义仍然生成非空约束,java,spring,postgresql,spring-boot,flyway,Java,Spring,Postgresql,Spring Boot,Flyway,我将Spring Boot和Flyway用于以下初始化脚本: CREATE TABLE ADDRESS( ID bigserial NOT NULL PRIMARY KEY ); CREATE TABLE ROLE( ID bigserial NOT NULL PRIMARY KEY ); CREATE TABLE PERSON( ID bigserial NOT NULL PRIMARY KEY, FIRST_NAME

我将Spring Boot和Flyway用于以下初始化脚本:

CREATE TABLE ADDRESS(
    ID bigserial NOT NULL PRIMARY KEY
                    );

CREATE TABLE ROLE(
    ID bigserial NOT NULL PRIMARY KEY
);

CREATE TABLE PERSON(
    ID bigserial NOT NULL PRIMARY KEY,
    FIRST_NAME VARCHAR(255),
    LAST_NAME VARCHAR(255),
    ADDRESS bigserial NOT NULL REFERENCES ADDRESS (ID),
    ROLE bigserial REFERENCES ROLE (ID)                  -- notice here is no 'not null'
);
表之间的所有关系是:

  • 每个
    都有
    0-1
    角色
    。因此,每个
    角色
    都属于
    0-n
    个人
    。因此,此关系可为空
  • 每个
    都有
    1
    地址
    。因此,每个
    地址
    都属于
    1-n
    个人
    。因此,此关系不是空的
一旦启动应用程序(我还尝试将查询直接发布到PostgreSQL数据库模式),就会在
PERSON
ROLE
表之间生成约束
not null

使用DataGrip,我选择SQL脚本->生成DDL以查询控制台并获取表的DDL(请参见下文,为了简洁起见,省略了新行和角色定义)

令我惊讶的是,
notnull
存在,尽管我还没有定义这样的约束。除了换桌子外,如何摆脱它

create table if not exists address
(
    id bigserial not null
        constraint address_pkey primary key
);

create table if not exists role
(
    id bigserial not nullconstraint role_pkey primary key
);

create table if not exists person
(
    id bigserial not null 
        constraint person_pkey primary key,
    first_name varchar(255),
    last_name varchar(255),
    address bigserial not null 
        constraint person_address_fkey references address,
    role bigserial not null                                   -- why is 'not null' here?
        constraint person_role_fkey references role
);

我使用的PostgreSQL版本(通过
SELECT version()
)是:

:

数据类型
smallserial
serial
bigserial
不正确 类型,但这仅仅是创建唯一 标识符列(类似于支持的
自动增量
属性 由其他一些数据库提供)。在当前实现中,指定:

CREATE TABLE tablename (
    colname SERIAL
);
CREATE SEQUENCE tablename_colname_seq AS integer;
CREATE TABLE tablename (
    colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
等同于指定:

CREATE TABLE tablename (
    colname SERIAL
);
CREATE SEQUENCE tablename_colname_seq AS integer;
CREATE TABLE tablename (
    colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
注意
不为空

不要对外键使用
bigserial
。那没有多大意义。只需使用
bigint

CREATE TABLE IF NOT EXISTS person
                           (...
                            role bigint REFERENCES role);
:

数据类型
smallserial
serial
bigserial
不正确 类型,但这仅仅是创建唯一 标识符列(类似于支持的
自动增量
属性 由其他一些数据库提供)。在当前实现中,指定:

CREATE TABLE tablename (
    colname SERIAL
);
CREATE SEQUENCE tablename_colname_seq AS integer;
CREATE TABLE tablename (
    colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
等同于指定:

CREATE TABLE tablename (
    colname SERIAL
);
CREATE SEQUENCE tablename_colname_seq AS integer;
CREATE TABLE tablename (
    colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
注意
不为空

不要对外键使用
bigserial
。那没有多大意义。只需使用
bigint

CREATE TABLE IF NOT EXISTS person
                           (...
                            role bigint REFERENCES role);

请注意,对于Postgres 10或更高版本,
identity
列建议优先于
serial
列:请注意,对于Postgres 10或更高版本,
identity
列建议优先于
serial
列:这在使用(推荐)时更为明显
identity
而不是
serial
我是否正确理解
bigserial
对于主键定义是好的,只要它指定了自动递增,并且
bigint
适合引用这些键?@nikolasharalalambidis:
bigint
是这里的基本实际数据类型。使用
bigserial
也是一种
bigint
,它只是添加了一些巫毒,以使用序列自动为列创建唯一值,就像一些宏,如果需要,可以展开。对于主键,这很方便。但是自动为外键创建值没有多大意义。他们只是或多或少地随机引用一条记录(至少可能不是您想要的记录),或者偶尔生成一个引用表中不存在的值,从而导致错误。这不太方便。使用(推荐)时,这一点更加明显
identity
而不是
serial
我是否正确理解
bigserial
对于主键定义是好的,只要它指定了自动递增,并且
bigint
适合引用这些键?@nikolasharalalambidis:
bigint
是这里的基本实际数据类型。使用
bigserial
也是一种
bigint
,它只是添加了一些巫毒,以使用序列自动为列创建唯一值,就像一些宏,如果需要,可以展开。对于主键,这很方便。但是自动为外键创建值没有多大意义。他们只是或多或少地随机引用一条记录(至少可能不是您想要的记录),或者偶尔生成一个引用表中不存在的值,从而导致错误。那不太方便。