PostgreSQL中使用CREATE TABLE AS能否复制表的Nullable约束?
问题
我在PostgreSQL中用以下语句创建空表:
CREATE TABLE IF NOT EXISTS table_yyymmdd AS TABLE parent_table WITH NO DATA;
创建成功后,子表table_yyymmdd的列名和数据类型都和父表一致,但所有列的Nullable约束都丢失了(父表中大部分列是not null,子表全变成可空)。想知道能不能通过CREATE TABLE AS语句直接复制父表的Nullable约束?
父表结构:
Column | Type | Collation | Nullable | Default ----------------------+-----------------------------+-----------+----------+------------------------- id | bigint | | not null | id_transaction | text | | not null | id_account | bigint | | not null | id_number | bigint | | not null | transaction_time | timestamp without time zone | | not null | now() amount | integer | | not null | fee | integer | | not null | validity | integer | | not null | notification_message | text | | |
子表结构:
Column | Type | Collation | Nullable | Default ----------------------+-----------------------------+-----------+----------+--------- id | bigint | | | id_transaction | text | | | id_account | bigint | | | id_number | bigint | | | transaction_time | timestamp without time zone | | | amount | integer | | | fee | integer | | | validity | integer | | | notification_message | text | | |
结论
不行,CREATE TABLE AS语句本身不支持复制原表的NOT NULL约束。这个语句的设计目标是基于查询结果创建表,只会复制列名、数据类型,以及部分由查询推导出来的属性,不会保留原表的约束(包括NOT NULL)、主键、外键、默认值(除非默认值是查询结果的一部分)等结构信息。
解决方案
方法1:使用CREATE TABLE ... LIKE(推荐)
PostgreSQL提供的LIKE语法专门用于复制表的完整结构,包括约束、默认值甚至索引:
CREATE TABLE IF NOT EXISTS table_yyymmdd LIKE parent_table INCLUDING ALL -- 包含所有约束、默认值、索引、存储参数等 WITH NO DATA;
如果只需要NOT NULL约束和默认值,不需要索引等其他内容,可以更精准地指定:
CREATE TABLE IF NOT EXISTS table_yyymmdd LIKE parent_table INCLUDING DEFAULTS -- 复制默认值 INCLUDING CONSTRAINTS -- 复制约束(含NOT NULL) WITH NO DATA;
方法2:CREATE TABLE AS + 手动添加约束
如果必须用CREATE TABLE AS,可以在创建表后手动补全NOT NULL约束和默认值:
-- 先创建空表 CREATE TABLE IF NOT EXISTS table_yyymmdd AS TABLE parent_table WITH NO DATA; -- 添加NOT NULL约束 ALTER TABLE table_yyymmdd ALTER COLUMN id SET NOT NULL, ALTER COLUMN id_transaction SET NOT NULL, ALTER COLUMN id_account SET NOT NULL, ALTER COLUMN id_number SET NOT NULL, ALTER COLUMN transaction_time SET NOT NULL, ALTER COLUMN amount SET NOT NULL, ALTER COLUMN fee SET NOT NULL, ALTER COLUMN validity SET NOT NULL; -- 补全默认值(比如transaction_time的now()) ALTER TABLE table_yyymmdd ALTER COLUMN transaction_time SET DEFAULT now();
内容的提问来源于stack exchange,提问作者c0ng111
相关产品推荐
相关产品推荐

