С учетом этой схемы:
CREATE TABLE parent (
parent_id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
last_updated TIMESTAMP DEFAULT NOW(),
UNIQUE(name)
);
CREATE TABLE child(
parent_id INT NOT NULL REFERENCES parent(parent_id),
data TEXT NOT NULL,
extra TEXT,
last_updated TIMESTAMP DEFAULT NOW(),
UNIQUE(data)
);
У меня есть вход, который должен произвести N вставок в родительскую таблицу с 1 или более вставками в дочернюю таблицу для каждой вставки в родительскую. Кроме того, этот ввод может обрабатываться несколько раз, и это не должно приводить к появлению дополнительных строк, а только к обновлению существующих.
Вот простая вставка, которая показывает, что я пытаюсь сделать:
WITH upserted_parent AS (
INSERT INTO parent (name)
VALUES ('parent1')
ON CONFLICT (name)
DO UPDATE SET last_updated = now()
RETURNING parent_id
) INSERT INTO child (
parent_id,
data,
extra
) VALUES (
(SELECT * FROM upserted_parent),
'data1',
'extra1'
), (
(SELECT * FROM upserted_parent),
'data2',
'extra2')
ON CONFLICT (data)
DO UPDATE SET extra = 'extra1', last_updated = now();
До этого момента я использовал psycopg2 execute
, передающий строку sql (с %(data)s
вместо строк) и набор аргументов (например, {'data': input['data']}
. Это больше не работает, когда один из этих аргументов список.
Есть ли способ сделать эти вставки за один вызов? Или, за исключением N вызовов, по одному на каждую родительскую вставку?