Удаление CTE в транзакции не может удалить дубликаты записей - PullRequest
0 голосов
/ 28 сентября 2018

Postgresql 10.1

ОШИБКА: дублирующееся значение ключа нарушает уникальное ограничение* Я пытаюсь здесь сделать следующее:

- В родительской таблице common_procedure я хочу изменить описание с «так что это» на «это тест».Это может легко вызвать конфликт в таблице common_procedure, если в результате две записи будут иметь одинаковое описание, поэтому первый CTE предназначен для удаления всех конфликтов в таблице common_procedure.

-Первый CTE предназначен для удалениялюбые конфликты в таблице common_procedure и возвращение UID из удаляемой записи и сохраняемой записи.

- Второй CTE предназначен для перемещения ссылки из (теперь удаленной) записи common_procedure в сохраненнуюзапись общего_процедура (хорошая).

-Последнее удаление предназначено для устранения любых возникающих дубликатов в таблице doctor_billing.

ЭТО СБОЙ! и каждая попытка IЯ сделал результаты по существу вышеупомянутой ошибки.Кажется, что аспекты удаления оператора всегда возникают перед вставками, поэтому таблицы остаются в состоянии ошибки.

МОЖЕТ ЛИ ЭТО СДЕЛАТЬ?

Спасибодля любой помощи или идей.

BEGIN;

    SET CONSTRAINTS ALL DEFERRED;

    UPDATE common_procedures cp
    SET description = 'this is a test'          
    WHERE cp.description ='so is this';   


    WITH _t(bad_uid, good_uid) AS (
        DELETE FROM
            common_procedures a
                USING common_procedures b
        WHERE
            a.recid > b.recid             
            AND a.description = b.description
        RETURNING a.uid, b.uid
    ),
    _t1 AS (
        UPDATE doctor_billing
        SET uid = _t.good_uid
        FROM _t
        WHERE uid = _t.bad_uid          
    )
DELETE FROM
        doctor_billing a
            USING doctor_billing b, _t
    WHERE
        a.recid > b.recid             
        AND a.uid = b.uid AND a.encounter_recid = b.encounter_recid AND a.uid = _t.good_uid;

COMMIT;

Вот определения таблицы (очень упрощенно):

CREATE TABLE common_procedures
(
    uid integer NOT NULL,
    description text NOT NULL,
    CONSTRAINT common_procedures_description_key UNIQUE (description)
        DEFERRABLE,
    CONSTRAINT common_procedures_uid UNIQUE (uid)
)

CREATE TABLE doctor_billing
(
    encounter_recid integer NOT NULL,
    uid integer NOT NULL,
    CONSTRAINT doctorbilling_encounter_unique UNIQUE (encounter_recid, uid)
        DEFERRABLE,
    CONSTRAINT doctor_billing_procedure_fk FOREIGN KEY (uid)
        REFERENCES nova.common_procedures (uid) MATCH SIMPLE
        ON UPDATE CASCADE
        ON DELETE RESTRICT
        DEFERRABLE
)

1 Ответ

0 голосов
/ 29 сентября 2018

Тьфу.Я полагаю, что ответ был опубликован здесь: https://stackoverflow.com/a/13807067/1547335 Несколько лет назад.

Короче говоря, две модификации данных cte с использованием одной и той же таблицы не должны использоваться вместе в одном и том же утверждении.Вот рабочая версия выше (с PetaPoco @'s).Обратите внимание, что изменение данных в разных таблицах выполняется одновременно, но окончательные операторы Delete были выделены.

BEGIN;
                                            SET CONSTRAINTS ALL DEFERRED;

                                            UPDATE common_procedures cp
                                            SET description =UPPER(TRIM( @0 ))                  
                                            WHERE UPPER(TRIM(cp.description)) = UPPER(TRIM(@1));    

                                            WITH _t(bad_uid, good_uid) AS (
                                                DELETE FROM
                                                    common_procedures a
                                                        USING common_procedures b
                                                WHERE
                                                    a.recid > b.recid            
                                                    AND a.description = b.description
                                                RETURNING a.uid, b.uid
                                            ),
                                             _t2 AS (
                                                UPDATE doctor_billing
                                                SET uid = _t.good_uid
                                                FROM _t
                                                WHERE uid = _t.bad_uid
                                            ),
                                            _t3 AS (
                                                UPDATE nurse_billing
                                                SET uid = _t.good_uid
                                                FROM _t
                                                WHERE uid = _t.bad_uid
                                            )
                                            UPDATE orders
                                            SET uid = _t.good_uid
                                            FROM _t
                                            WHERE uid = _t.bad_uid;

                                        DELETE FROM
                                                doctor_billing a
                                                    USING doctor_billing b
                                            WHERE
                                                a.recid > b.recid             
                                                AND a.uid = b.uid AND a.encounter_recid = b.encounter_recid;

                                        COMMIT; 
...