TG Telegram Group & Channel
Zen of Python | United States America (US)
Create: Update:

Молчаливый «провал» INSERT

Вы запускаете SQL-запрос INSERT, и вроде всё просто. Нет ошибок. Но и данные не вставлены. Звучит странно? Такое действительно может случиться с PostgreSQL — и случается чаще, чем хотелось бы.


Как можно вставить данные и не вставить одновременно?

Когда INSERT не срабатывает, первое, что приходит в голову — ошибка. Но PostgreSQL умеет «глотать» такое — ведь вы сами его об этом попросили.

Виновник — ON CONFLICT DO NOTHING



INSERT INTO users (id, email)
VALUES (42, '[email protected]')
ON CONFLICT (id) DO NOTHING;


Здесь мы явно говорим: "если произойдёт конфликт по id, ничего не делай". И PostgreSQL по умолчанию так и поступает.


Поведение UPSERT при множественных уникальных индекса

Представьте, что в таблице есть не один, а два уникальных индекса:


CREATE TABLE users (
id SERIAL PRIMARY KEY,
email TEXT UNIQUE,
username TEXT UNIQUE
);


Теперь вы выполняете:


INSERT INTO users (email, username)
VALUES ('[email protected]', 'johnny');


А если username = 'johnny' уже существует, но email ещё нет?

Вставка завершится ошибкой!

Так происходит, потому что ON CONFLICT (email) говорит PostgreSQL: «молчи, если конфликт по email, но бросай ошибку, если конфликт по чему-то ещё».

Чтобы избежать этого, используем:


ON CONFLICT DO NOTHING


Тогда PostgreSQL проигнорирует конфликт по любому индексу. Но это может спровоцировать проблемы, особенно при вставке пачкой


Как отладить такую ситуацию?

Проверяйте rowcount после запроса. В Python/psycopg2, например:


cursor.execute(sql, values)
if cursor.rowcount == 0:
print("Nothing inserted!")


— Добавьте RETURNING и логируйте:


INSERT INTO users (email, username)
VALUES ('[email protected]', 'johnny')
ON CONFLICT DO NOTHING
RETURNING id;


Если возвращается пустой результат — значит, вставки не было.

— Логируйте причину. Если вы используете логику вида DO UPDATE, можно добавить логи в `UPDATE`-часть или сохранять «причину отказа» отдельно.

#sql

Молчаливый «провал» INSERT

Вы запускаете SQL-запрос INSERT, и вроде всё просто. Нет ошибок. Но и данные не вставлены. Звучит странно? Такое действительно может случиться с PostgreSQL — и случается чаще, чем хотелось бы.


Как можно вставить данные и не вставить одновременно?

Когда INSERT не срабатывает, первое, что приходит в голову — ошибка. Но PostgreSQL умеет «глотать» такое — ведь вы сами его об этом попросили.

Виновник — ON CONFLICT DO NOTHING



INSERT INTO users (id, email)
VALUES (42, '[email protected]')
ON CONFLICT (id) DO NOTHING;


Здесь мы явно говорим: "если произойдёт конфликт по id, ничего не делай". И PostgreSQL по умолчанию так и поступает.


Поведение UPSERT при множественных уникальных индекса

Представьте, что в таблице есть не один, а два уникальных индекса:


CREATE TABLE users (
id SERIAL PRIMARY KEY,
email TEXT UNIQUE,
username TEXT UNIQUE
);


Теперь вы выполняете:


INSERT INTO users (email, username)
VALUES ('[email protected]', 'johnny');


А если username = 'johnny' уже существует, но email ещё нет?

Вставка завершится ошибкой!

Так происходит, потому что ON CONFLICT (email) говорит PostgreSQL: «молчи, если конфликт по email, но бросай ошибку, если конфликт по чему-то ещё».

Чтобы избежать этого, используем:


ON CONFLICT DO NOTHING


Тогда PostgreSQL проигнорирует конфликт по любому индексу. Но это может спровоцировать проблемы, особенно при вставке пачкой


Как отладить такую ситуацию?

Проверяйте rowcount после запроса. В Python/psycopg2, например:


cursor.execute(sql, values)
if cursor.rowcount == 0:
print("Nothing inserted!")


— Добавьте RETURNING и логируйте:


INSERT INTO users (email, username)
VALUES ('[email protected]', 'johnny')
ON CONFLICT DO NOTHING
RETURNING id;


Если возвращается пустой результат — значит, вставки не было.

— Логируйте причину. Если вы используете логику вида DO UPDATE, можно добавить логи в `UPDATE`-часть или сохранять «причину отказа» отдельно.

#sql


>>Click here to continue<<

Zen of Python




Share with your best friend
VIEW MORE

United States America Popular Telegram Group (US)