У меня есть такие пары, как (<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
в других языках программирования
Откуда должны взяться все эти пары?
@Сергей. Но у меня нет конфликта. Первое и второе значения не уникальны в таблице. Но мне нужны уникальные пары. (1, 1) (2,1) или (1, 1) (1,2) - Хорошо. (1,1) (1,1) - Не в порядке
Пары @Serg из python dict. И я бы не хотел сначала запрашивать все пары, проверять уникальность через python, а затем добавлять уникальные. Я хотел бы сделать все в sql
Является ли (first_column, second_column) уникальным ключом в таблице? Тогда можно insert .. on conflict do nothing
@Серг. Нет. Посмотрите на третий комментарий. Значения в таблице не уникальны. Только id уникален. Но это пары значений, которые должны быть уникальными.
Если они должны быть уникальными, сделайте их уникальными. Добавьте индекс UNIQUE
к (first_column, second_column)
, тогда вы сможете использовать ON CONFLICT
.
<table_name>(<first_column>, <second_column>)
Кстати: пожалуйста, не используйте метасинтаксис или псевдокод. Используйте реальный код с реальными именами.
Если оба ваши условия ложны, ваш запрос пытается вставить нулевые значения в два столбца. Это не подходит. В этом случае вам нужно вставить ноль ряды с двумя столбцами.
В 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
)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
Я думаю, вы можете прочитать в руководстве по PostgreSQL о предложении ON CONFLICT.