CREATE as SELECT with CONSTRAINT?

Rob*_*rde 8 postgresql database-design constraint

我有一块在 PostgreSQLSQL中创建了TABLE一个SELECT语句;我想向表中添加约束,例如,一列不能是null.

我在 Postgres 文档中找不到对此有效的 SQL,因此似乎不可能。

实现这种功能的最佳方法是什么?如果违反约束,我希望表的创建失败。

我无法预先创建带有约束的表,因为某些列可能存在一些变化,因为它们是动态过程的结果。

ype*_*eᵀᴹ 10

@a_horse_with_no_name 的答案的一个变体是首先使用约束创建表,然后插入到表中,仍然使用事务,因此在违反约束的情况下一切都会回滚。如果要插入的行很多(即数十万或数百万),您应该考虑这一点。

如果很难create table动态创建语句,您可以将该部分分成 2 个语句,如下所示:

begin transaction ;
    create table new_table                       -- create the table
    as
    select v.*
    from (select ....) as v                      -- as before
    where false ;                                -- but insert 0 rows

    alter table new_table add constraint ... ;   -- add the constraint

    insert into new_table                        -- and then attempt
    select ... ;                                 -- the insert
end ;
Run Code Online (Sandbox Code Playgroud)

与另一种方式的区别在于约束将在任何行插入表中之前存在。由于NOT NULLCHECK约束不可延迟,但总是在插入或修改行时(而不是在语句末尾)立即检查,因此您的插入语句将失败(并回滚),并且第一行违反了您的约束已经放置。

如果您要插入数百万行,它会更快,因为它可能会更快地发现错误,而且因为它必须回滚更少的插入。

  • 很好的一点 (2认同)

a_h*_*ame 5

你需要用两个语句来做到这一点:

create table new_table
as
select ....;

alter table new_table add constraint ...;
Run Code Online (Sandbox Code Playgroud)

确保在单个事务中运行它(例如通过关闭 SQL 客户端中的自动提交,或用 begin transaction ...

如果alter table失败,您可以回滚所有内容并且该表也消失了。