外键的 Flyway 和 PostgreSQL 可空定义仍然生成非空约束
Flyway and PostgreSQL nullable definition of foreign key still generates a non-null constraint
我将 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'
);
所有table之间的关系是:
- 每个
PERSON
有 0-1
ROLE
。因此,每个 ROLE
属于 0-n
PERSON
。因此,这种关系可以为空。
- 每个
PERSON
有 1
ADDRESS
。因此,每个 ADDRESS
属于 1-n
PERSON
。因此,这种关系不是空的。
一旦我启动应用程序(我也尝试 post 查询直接到 PostgreSQL 数据库模式),就会以某种方式生成约束 not-null
PERSON
和 ROLE
tables.
使用 DataGrip,我 select SQL 脚本 -> 生成 DDL 以查询控制台 并获取tables 的 DDL(见下文,为简洁起见省略了新行和角色定义)。
令我惊讶的是,NOT NULL
在那里,尽管我没有定义这样的约束。除了改变 table 之外如何摆脱它?
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
);
我使用的(通过SELECT version()
)的PostgreSQL版本是:
PostgreSQL 10.13, compiled by Visual C++ build 1800, 64-bit
The data types smallserial
, serial
and bigserial
are not true
types, but merely a notational convenience for creating unique
identifier columns (similar to the AUTO_INCREMENT
property supported
by some other databases). In the current implementation, specifying:
CREATE TABLE tablename (
colname SERIAL
);
is equivalent to specifying:
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;
注意 NOT NULL
。
不要使用 bigserial
作为 外键 键。那没有多大意义。只需使用 bigint
.
CREATE TABLE IF NOT EXISTS person
(...
role bigint REFERENCES role);
可能的解决方案一:
将 Biserial
更改为 Bigint
不会删除在 运行 springboot 中的 flyway 写入 postgres DB 时设置为外键列的空约束(至少对于我的情况)
- postgres:11.3-alphine 3.4
- 飞行路线:8.0.5
为了安全起见,需要添加脚本来将列更改为可为空
ALTER TABLE mytable ALTER COLUMN mycolumn DROP NOT NULL;
Change Postgres column to nullable
可能的解决方案2:
当 Spring 引导将 JPA Hibernate ddl 配置设置为 create
、create-drop
、update
时,flyway DB 迁移脚本将由 JPA 实体属性更新。 JPA 实体可以添加 NOT NULL 约束。
将 JPA Hibernate ddl 配置更改为 none
或 validate
将确保仅使用 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 VARCHAR(255),
LAST_NAME VARCHAR(255),
ADDRESS bigserial NOT NULL REFERENCES ADDRESS (ID),
ROLE bigserial REFERENCES ROLE (ID) -- notice here is no 'not null'
);
所有table之间的关系是:
- 每个
PERSON
有0-1
ROLE
。因此,每个ROLE
属于0-n
PERSON
。因此,这种关系可以为空。 - 每个
PERSON
有1
ADDRESS
。因此,每个ADDRESS
属于1-n
PERSON
。因此,这种关系不是空的。
一旦我启动应用程序(我也尝试 post 查询直接到 PostgreSQL 数据库模式),就会以某种方式生成约束 not-null
PERSON
和 ROLE
tables.
使用 DataGrip,我 select SQL 脚本 -> 生成 DDL 以查询控制台 并获取tables 的 DDL(见下文,为简洁起见省略了新行和角色定义)。
令我惊讶的是,NOT NULL
在那里,尽管我没有定义这样的约束。除了改变 table 之外如何摆脱它?
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
);
我使用的(通过SELECT version()
)的PostgreSQL版本是:
PostgreSQL 10.13, compiled by Visual C++ build 1800, 64-bit
The data types
smallserial
,serial
andbigserial
are not true types, but merely a notational convenience for creating unique identifier columns (similar to theAUTO_INCREMENT
property supported by some other databases). In the current implementation, specifying:CREATE TABLE tablename ( colname SERIAL );
is equivalent to specifying:
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;
注意 NOT NULL
。
不要使用 bigserial
作为 外键 键。那没有多大意义。只需使用 bigint
.
CREATE TABLE IF NOT EXISTS person
(...
role bigint REFERENCES role);
可能的解决方案一:
将 Biserial
更改为 Bigint
不会删除在 运行 springboot 中的 flyway 写入 postgres DB 时设置为外键列的空约束(至少对于我的情况)
- postgres:11.3-alphine 3.4
- 飞行路线:8.0.5
为了安全起见,需要添加脚本来将列更改为可为空
ALTER TABLE mytable ALTER COLUMN mycolumn DROP NOT NULL;
Change Postgres column to nullable
可能的解决方案2:
当 Spring 引导将 JPA Hibernate ddl 配置设置为 create
、create-drop
、update
时,flyway DB 迁移脚本将由 JPA 实体属性更新。 JPA 实体可以添加 NOT NULL 约束。
将 JPA Hibernate ddl 配置更改为 none
或 validate
将确保仅使用 flyway 脚本来创建模式。