Postgres。插入多行不存在的行

发布于 2025-01-15 10:02:46 字数 1139 浏览 3 评论 0原文

我有像 (,) 这样的对,并且我有具有以下结构的表:

_____________________________________
| id | first_column | second_column |
 

我需要插入所有尚不存在的对。 我认为我需要类似 INSERT IF NOT EXIST 但对于每一对。

我尝试使用此代码:

INSERT INTO <table_name>(<first_column>, <second_column>) 
VALUES (CASE 
            WHEN NOT EXISTS (
                SELECT 1 
                FROM <table_name>
                WHERE <first_column> = <pair_1_value_1> AND <second_column> = <pair_1_value_2>
            ) THEN (<pair_1_value_1>, <pair_1_value_2>) 
    
            WHEN NOT EXISTS (
                SELECT 1 
                FROM <table_name>
                WHERE <first_column> = <pair_2_value_1> AND <second_column> = <pair_2_value_2>
            ) THEN (<pair_2_value_1>, <pair_2_value_2>) 

            .....

         END
);

但出现此错误:INSERT 的目标列多于表达式。另外,我认为它不起作用,因为它只会插入第一个通过条件的一行。作为其他编程语言中的 if - elif - else 运算符

I have pairs like (<first_value>, <second_value>) and I have table with following structure:

_____________________________________
| id | first_column | second_column |
 

I need to insert all pairs which do not exist already.
I think that I need something like INSERT IF NOT EXIST but for every pair.

I try use this code:

INSERT INTO <table_name>(<first_column>, <second_column>) 
VALUES (CASE 
            WHEN NOT EXISTS (
                SELECT 1 
                FROM <table_name>
                WHERE <first_column> = <pair_1_value_1> AND <second_column> = <pair_1_value_2>
            ) THEN (<pair_1_value_1>, <pair_1_value_2>) 
    
            WHEN NOT EXISTS (
                SELECT 1 
                FROM <table_name>
                WHERE <first_column> = <pair_2_value_1> AND <second_column> = <pair_2_value_2>
            ) THEN (<pair_2_value_1>, <pair_2_value_2>) 

            .....

         END
);

But I get this error: INSERT has more target columns than expressions. Also, I thought it wouldn't work because it would only insert the one line that first passes the condition. As a if - elif - else operators in other programing languages

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

甲如呢乙后呢 2025-01-22 10:02:46

如果您的条件两者都为假,您的查询将尝试将零值插入到两列中。那是不合适的。在这种情况下,您需要插入零和两列。

SQL中没有IF;不要试图模仿它。有 WHERE


CREATE TABLE omg
        ( first_column text
        , second_column text
        , PRIMARY KEY (first_column, second_column)
        );

WITH wtf (one,two) AS (
        VALUES ( 'aa', 'ab')
             , ( 'ba', 'bb')
        )
INSERT INTO omg(first_column, second_column)
SELECT one, two
FROM wtf w
WHERE NOT EXISTS (
        SELECT*
        FROM omg nx
        WHERE nx.first_column = w.one
        AND nx.second_column = w.two
        )
        ;

在您的实际代码中,最好是:

  • 创建一个临时表 (CREATE TEMP TABLE wtf as SELECT * FROM omg where 0=1)
  • insert 将所有值(来自您的Python代码)放入此临时表中,
  • 从此临时表中选择(不同)(而不是从wtf CTE)

If both your conditions are false, your query attempts to insert zero values into two columns. That is not going to fit. In that case you need to insert zero rows with two columns.

There is no IF in SQL; don't try to emulate it. There is WHERE :


CREATE TABLE omg
        ( first_column text
        , second_column text
        , PRIMARY KEY (first_column, second_column)
        );

WITH wtf (one,two) AS (
        VALUES ( 'aa', 'ab')
             , ( 'ba', 'bb')
        )
INSERT INTO omg(first_column, second_column)
SELECT one, two
FROM wtf w
WHERE NOT EXISTS (
        SELECT*
        FROM omg nx
        WHERE nx.first_column = w.one
        AND nx.second_column = w.two
        )
        ;

In your actual code it is probably better to:

  • create a temp table (CREATE TEMP TABLE wtf as SELECT * FROM omg where 0=1)
  • insert all the values (from your Python code) into this temp table
  • select (distinct) from this temp table (instead of from the wtf CTE)
花伊自在美 2025-01-22 10:02:46

MERGE 语句没有完全满足您的需要吗?
这个例子似乎按照你所描述的那样工作,至少对我来说:

CREATE TABLE tgt (a,b) AS (
            SELECT 'A','A'
  UNION ALL SELECT 'B','B'
  UNION ALL SELECT 'C','C'
  UNION ALL SELECT 'D','D'
  UNION ALL SELECT 'E','E'
  UNION ALL SELECT 'F','F'
  UNION ALL SELECT 'G','G'
  UNION ALL SELECT 'H','H'
  UNION ALL SELECT 'I','I'
  UNION ALL SELECT 'J','J'
)
;
-- out CREATE TABLE
MERGE INTO tgt
USING (
  SELECT 'A','A' UNION ALL
  SELECT 'K','K' UNION ALL
  SELECT 'L','L'
) src(a,b)
  ON src.a=tgt.a
 AND src.b=tgt.b
WHEN NOT MATCHED THEN
  INSERT VALUES (src.a,src.b)
;
-- out  OUTPUT 
-- out --------
-- out       2
SELECT * FROM tgt;
-- out  a | b 
-- out ---+---
-- out  A | A
-- out  B | B
-- out  C | C
-- out  D | D
-- out  E | E
-- out  F | F
-- out  G | G
-- out  H | H
-- out  I | I
-- out  J | J
-- out  K | K
-- out  L | L

Doesn't the MERGE statement do exactly what you need?
This example seems to work as you describe, at least to me:

CREATE TABLE tgt (a,b) AS (
            SELECT 'A','A'
  UNION ALL SELECT 'B','B'
  UNION ALL SELECT 'C','C'
  UNION ALL SELECT 'D','D'
  UNION ALL SELECT 'E','E'
  UNION ALL SELECT 'F','F'
  UNION ALL SELECT 'G','G'
  UNION ALL SELECT 'H','H'
  UNION ALL SELECT 'I','I'
  UNION ALL SELECT 'J','J'
)
;
-- out CREATE TABLE
MERGE INTO tgt
USING (
  SELECT 'A','A' UNION ALL
  SELECT 'K','K' UNION ALL
  SELECT 'L','L'
) src(a,b)
  ON src.a=tgt.a
 AND src.b=tgt.b
WHEN NOT MATCHED THEN
  INSERT VALUES (src.a,src.b)
;
-- out  OUTPUT 
-- out --------
-- out       2
SELECT * FROM tgt;
-- out  a | b 
-- out ---+---
-- out  A | A
-- out  B | B
-- out  C | C
-- out  D | D
-- out  E | E
-- out  F | F
-- out  G | G
-- out  H | H
-- out  I | I
-- out  J | J
-- out  K | K
-- out  L | L
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文