【问题标题】:INSERT using SELECT from potentially empty table使用 SELECT 从可能为空的表中插入
【发布时间】:2016-02-03 03:39:39
【问题描述】:

我有一个 postgres 数据库架构,其中新插入的行引用其他行。表格的骨架是:

CREATE TABLE table_1 (
    f1    UUID PRIMARY KEY,
    f2    UUID NOT NULL,
    f3    text NOT NULL,
    f4    text NOT NULL DEFAULT '',
    f5    text NOT NULL DEFAULT '',
    f6    UUID NULL,
);

这是我正在使用的 INSERT 查询:

INSERT INTO table_a (f1, f2, f3, f4, f5, f6)
SELECT               $1, $2, $3, f4, f5, f2
FROM        table_a
WHERE       <conditionals>
ORDER BY    <ordering>
LIMIT       1

基本思想是寻找满足条件的现有行。如果存在,则使用字段 f4、f5 和 f2 来填充要插入的新行中的字段 f4、f5 和 f6。如果不存在,则这些字段应采用其默认值(分别为''、'' 和 NULL)。

问题是,如果没有找到任何行,SELECT 本身似乎没有返回任何结果,并且整个插入被简单地跳过。如果一行与条件匹配,则它可以正常工作,但如果该 SELECT 没有返回任何行,则不会。如何获得所需的行为?

【问题讨论】:

    标签: postgresql


    【解决方案1】:
    insert into table_a (f1, f2, f3, f4, f5, f6)
    select f1, f2, f3, f4, f5, f6
    from (
        (
            select $1, $2, $3, f4, f5, f2, 1
            from table_a
            where <conditionals>
            order by <ordering>
            limit 1
        ) s
        union all
        select $1, $2, $3, '', '', null, 2
    ) s (f1, f2, f3, f4, f5, f6, o)
    order by o
    limit 1
    

    【讨论】:

      【解决方案2】:

      如果您想使用表 DDL 中的默认值而不是在查询中硬编码,这只是另一种方式:

      WITH t AS (
        INSERT INTO table_a (f1, f2, f3, f4, f5, f6)
        SELECT               $1, $2, $3, f4, f5, f2
        FROM        table_a
        WHERE       <conditionals>
        ORDER BY    <ordering>
        LIMIT       1
        RETURNING *) -- This query will return inserted values
      INSERT INTO table_a (f1, f2, f3)
      SELECT $1, $2, $3 WHERE (SELECT count(*) FROM t) = 0; -- Insert if no insertion was happened at WITH clause
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-12-03
        • 2013-05-28
        • 1970-01-01
        • 2010-09-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-17
        相关资源
        最近更新 更多