Semenych
@Semenych
Solution Architect

PostgreSQL: вставка нескольких (миллионов) строк, как увидеть все строки которые нарушают constrants?

UPD я знаю как отбирать ТОЛЬКО строки которые не нарушают констрейнты. Мне нужно именно все ошибки получить, если такое возможно

UPD2 после первой ошибки мне уже не интересно, какие данные вставятся, можно никакие, мне надо знать все причины по которым они не вставятся. Я понимаю, что это немного теоретическое упражнение и в приличной СУБД такого быть не может. Но возможно все же есть хитрый хак.


Мы переливаем данные из одной базы в другую. При вставке строк командой "insert from select" несколько строк нарушают какие-то ограничения, как правило FOREIGN KEY. Как бы при вставке увидеть не первую строку которая вызвала ошибку, а все. Например

create table t_source (id int, ref int);
insert into t_source (id,ref) values (1,1),(1,2),(1,3),(1,4),(1,5);

create table t_dict(id int primary KEY, name varchar);
insert into t_dict (id,name) values (2,'two'),(3,'three');

create table t_target (
 id int, ref int,
 FOREIGN KEY (ref) REFERENCES t_dict(id)
);

insert into t_target (id,ref) select id,ref from t_source;


выдает
SQL Error [23503]: ERROR: insert or update on table "t_target" violates foreign key constraint "t_target_ref_fkey"
Detail: Key (ref)=(1) is not present in table "t_dict".


А как бы увидеть строки 1,4,5
Про where not in я знаю, но он не подходит потому, что реальный запрос строк так на 150, данных 3 ТБ, нарушаться может много разных констрейнтов для разных данных и мне не надо их игнорировать, а надо посылать специальных людей фиксить в исходной БД. Сейчас мы это делаем именно с помощью серии where not in и повторных запросов которые выбирают нам разницу, но это долго и дорого, а вот если бы можно было увидеть все ошибки сразу это бы сильно ускорило работу.

Т.е. мне действительно надо увидеть все ошибки, а не найти обходное решение. И про курсор я тоже знаю, но он мне не походит т.к. с ним сильно медленнее.
  • Вопрос задан
  • 573 просмотра
Пригласить эксперта
Ответы на вопрос 2
Melkij
@Melkij
PostgreSQL DBA
Добавить в insert ... select проверку данных самостоятельно.
where exists(select from t_dict where t_dict.id = t_source.ref)

Затем взять, соответственно, not exists список и пойти с этим списком пинать "хде данные"

Проигнорировать ошибку хотя бы одной строки будет дико дорого по ресурсам.
Ответ написан
@gram2005
SELECT t_source.ref FROM t_source
LEFT JOIN t_dict ON t_source.ref = t_dict.id
WHERE t_dict.id IS NULL;

t_source.ref должен быть проиндексирован.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы