Постгрес. Вставить несколько строк, которые не существуют

У меня есть такие пары, как (<first_value>, <second_value>), и у меня есть таблица со следующей структурой:

_____________________________________
| 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 has more target columns than expressions. Кроме того, я думал, что это не сработает, потому что будет вставлена ​​только одна строка, которая первой проходит условие. Как операторы if - elif - else в других языках программирования

Я думаю, вы можете прочитать в руководстве по PostgreSQL о предложении ON CONFLICT.

Sergey 19.03.2022 18:20

Откуда должны взяться все эти пары?

Serg 19.03.2022 18:26

@Сергей. Но у меня нет конфликта. Первое и второе значения не уникальны в таблице. Но мне нужны уникальные пары. (1, 1) (2,1) или (1, 1) (1,2) - Хорошо. (1,1) (1,1) - Не в порядке

Prosto_Oleg 19.03.2022 18:26

Пары @Serg из python dict. И я бы не хотел сначала запрашивать все пары, проверять уникальность через python, а затем добавлять уникальные. Я хотел бы сделать все в sql

Prosto_Oleg 19.03.2022 18:28

Является ли (first_column, second_column) уникальным ключом в таблице? Тогда можно insert .. on conflict do nothing

Serg 19.03.2022 18:32

@Серг. Нет. Посмотрите на третий комментарий. Значения в таблице не уникальны. Только id уникален. Но это пары значений, которые должны быть уникальными.

Prosto_Oleg 19.03.2022 18:37

Если они должны быть уникальными, сделайте их уникальными. Добавьте индекс UNIQUE к (first_column, second_column), тогда вы сможете использовать ON CONFLICT.

Adrian Klaver 19.03.2022 18:43
<table_name>(<first_column>, <second_column>) Кстати: пожалуйста, не используйте метасинтаксис или псевдокод. Используйте реальный код с реальными именами.
wildplasser 19.03.2022 19:34
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
8
43
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Если оба ваши условия ложны, ваш запрос пытается вставить нулевые значения в два столбца. Это не подходит. В этом случае вам нужно вставить ноль ряды с двумя столбцами.

В 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)
  • вставьте все значения (из вашего кода Python) в эту временную таблицу
  • выберите (отчетливый) из этой временной таблицы (вместо wtf CTE)

Разве оператор 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

Другие вопросы по теме