在upsert函数中哪里不存在错误

时间:2014-06-09 13:39:25

标签: sql postgresql plpgsql

我为postgresql编写强大的upsert函数有很多帮助。我试图将值插入到具有3列的表中,两个是外键,一个是文本。

我有一个非常相似的功能,效果很好,它只是没有像这样的子查询。我收到了错误

"ERROR:  syntax error at or near "WHERE"
LINE 24:   WHERE NOT EXISTS (SELECT 1 FROM sel)"

功能:

create or replace function upsert_dish_cluster_to_network(n_id INT, c_id INT, amsover TEXT)
RETURNS SETOF dish_cluster_to_network AS 
$func$
BEGIN

LOOP
    BEGIN

    RETURN QUERY
    WITH sel AS (
        SELECT dctn.id
        FROM   dish_cluster_to_network dctn
        WHERE  dctn.network_id = (SELECT id FROM unv_network WHERE amscode = n_id)
        AND    dctn.cluster_id = (SELECT id FROM dish_cluster_network WHERE axsyscode = c_id)
        FOR    SHARE
        ),
         ins AS (
        INSERT INTO dish_cluster_to_network (network_id, cluster_id, amsname_override)
        VALUES (
            (SELECT id FROM unv_network WHERE amscode = n_id),
            (SELECT id from dish_cluster_network WHERE axsyscode = c_id),
            amsover
            )
        WHERE NOT EXISTS (SELECT 1 FROM sel)
        RETURNING *
        ),
         upd AS (
        UPDATE dish_cluster_to_network dctn
        SET    network_id       = (SELECT id from unv_network WHERE amscode = n_id),
               cluster_id       = (SELECT id from dish_cluster_network WHERE axsyscode = c_id),
               amsname_override = amsover
        FROM   sel
        WHERE  sel.id = dctn.id
        AND    (      dctn.network_id    IS DISTINCT FROM (SELECT id FROM unv_network WHERE amscode = n_id)
            OR    dctn.cluster_id    IS DISTINCT FROM (SELECT id FROM dish_cluster_network WHERE axsyscode = c_id)
            )
        RETURNING dctn.*
        )
    SELECT * FROM ins
    UNION ALL
    SELECT * FROM upd;

    RETURN;

    EXCEPTION WHEN UNIQUE_VIOLATION THEN
        RAISE NOTICE 'Something Bad Happened';
    END;
END LOOP;

END
$func$ LANGUAGE plpgsql;

我无法弄清楚为什么我不能拥有WHERE NOT EXISTS行。如果我注释掉该行,该函数总是插入新条目并且永远不会更新。

1 个答案:

答案 0 :(得分:1)

insert命令没有where子句。因此,将values替换为select

ins AS (
    INSERT INTO dish_cluster_to_network (
        network_id, cluster_id, amsname_override
    )
    select
       (SELECT id FROM unv_network WHERE amscode = n_id),
       (SELECT id from dish_cluster_network WHERE axsyscode = c_id),
       amsover
    WHERE NOT EXISTS (SELECT 1 FROM sel)
    RETURNING *
),