DBVis / PL SQL: ЕСЛИ СУЩЕСТВУЕТ - как правильно структурировать, если это возможно - PullRequest
0 голосов
/ 08 января 2020

Используя DBVis SQL commander (так как я использую «начало» и «конец» в этом коде, я считаю, что этот код выполняется в стиле PL SQL) Я пытаюсь выполнить сценарий sql Я написал, чтобы быть моим новым «триггером очистки»

Я пытаюсь использовать операторы IF EXISTS в этом скрипте для достижения очистки ТОЛЬКО, когда определенный столбец действительно содержит данные (УТВЕРЖДЕНО или ОТКАЗАНО)

Этот сценарий направлен на то, чтобы НЕ использовать операторы вставки (для других таблиц) (они будут запускать другие триггеры в других таблицах нежелательным образом, если они используются, даже если для них нет данных для вставки), за исключением случаев, когда они есть ( не нулевые) данные в определенном столбце:

begin

IF EXISTS (SELECT * 
        FROM HUB_SEGMENTS 
        where APP_OR_REJECT = 'APPROVED' or APP_OR_REJECT = 'REJECTED')
        THEN
INSERT INTO
 HUB_APPROVED (HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE)
         SELECT 
         HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE 
         FROM 
         HUB_SEGMENTS WHERE APP_OR_REJECT = 'APPROVED';

INSERT INTO
 HUB_REJECTED (HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE)
         SELECT 
         HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE 
         FROM 
         HUB_SEGMENTS WHERE APP_OR_REJECT = 'REJECTED';     

DELETE
FROM
    "TESTDEMO".HUB_SEGMENTS
WHERE
    APP_OR_REJECT = 'APPROVED' or APP_OR_REJECT = 'REJECTED';
    DBMS_OUTPUT.PUT_LINE('Trigger: Insert to action Tables Executed');


ELSE 

    DBMS_OUTPUT.PUT_LINE('Trigger: Insert to action Tables Not Executed');

end;

К сожалению, я получаю следующее сообщение об ошибке при попытке запустить это:

[Код: 6550, SQL Состояние : 65000] ORA-06550: строка 33, столбец 4: PLS-00103: Обнаружен символ ";" ожидая одного из следующего: если

Я почти уверен, что это связано с тем, как я структурировал IF EXIST

Конечно, это может быть то, что с использованием IF EXIST в DBVis SQL commander, в моем коде PL SQL, недопустим - я не видел много документации для этого специфического оператора c из oracle. Если так, был бы другой способ, которым я мог бы попытаться выполнить sh, что я пытаюсь сделать здесь?

Любое руководство будет с благодарностью

Ответы [ 3 ]

1 голос
/ 08 января 2020

Это структура вашего кода:

BEGIN
    IF EXISTS (SELECT... FROM HUB_SEGMENTS WHERE APP_OR_REJECT = 'APPROVED' or APP_OR_REJECT = 'REJECTED')
        THEN
            INSERT INTO HUB_APPROVED SELECT ... FROM FROM HUB_SEGMENTS WHERE APP_OR_REJECT = 'APPROVED';
            INSERT INTO HUB_REJECTED SELECT ... FROM FROM HUB_SEGMENTS WHERE APP_OR_REJECT = 'REJECTED';
            DELETE FROM HUB_SEGMENTS WHERE APP_OR_REJECT = 'APPROVED' or APP_OR_REJECT = 'REJECTED';
        ELSE
            ...;
END;

Вы можете легко увидеть, что отступы переходят на уровень до финального END: вам не хватает END IF, закрывающего блок IF , Oracle пытается сообщить вам об этом, давая вам строку, соответствующую окончательному end; и говоря: Обнаружил символ ; при ожидании одного из следующих действий: if.

BEGIN
    IF EXISTS (SELECT... FROM HUB_SEGMENTS WHERE APP_OR_REJECT IN ('APPROVED', 'REJECTED');
        THEN
            INSERT INTO HUB_APPROVED SELECT ... FROM FROM HUB_SEGMENTS WHERE APP_OR_REJECT = 'APPROVED';
            INSERT INTO HUB_REJECTED SELECT ... FROM FROM HUB_SEGMENTS WHERE APP_OR_REJECT = 'REJECTED';
            DELETE FROM HUB_SEGMENTS WHERE APP_OR_REJECT IN ('APPROVED', 'REJECTED');
        ELSE
            ...;
    END IF;             --> here
END;

Бонус: вы можете использовать IN вместо этих OR ed условий.

Примечание: если производительность не имеет значения, то, как предлагает @zip, не возиться с блоком IF. Вы можете напрямую запускать два оператора INSERT s и оператор DELETE один за другим. Если в HUB_SEGMENTS нет данных, соответствующих критериям поиска, то все равно ничего не будет вставлено или удалено.

1 голос
/ 08 января 2020

Вам не нужно, если существует, я верю Просто поверните

IF EXISTS (SELECT * 
        FROM HUB_SEGMENTS 
        where APP_OR_REJECT = 'APPROVED' or APP_OR_REJECT = 'REJECTED')
        THEN
INSERT INTO
 HUB_APPROVED (HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE)
         SELECT 
         HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE 
         FROM 
         HUB_SEGMENTS WHERE APP_OR_REJECT = 'APPROVED';

К

INSERT INTO
 HUB_APPROVED (HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE)
         SELECT 
         HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE 
         FROM 
         HUB_SEGMENTS where (APP_OR_REJECT = 'APPROVED' or APP_OR_REJECT = 'REJECTED');
0 голосов
/ 14 января 2020

спасибо за полезные комментарии - они сработали бы, если бы я использовал не oracle SQL (возможно?). К сожалению, запуск сценария PL / SQL с «существует» в DBV, на который указывает oracle дБ, приводит к ошибке - Exists не работает в сценариях PL / SQL (но, очевидно, должен в одиночных операторах SQL).

Я обнаружил, что использование переменной в сочетании с IF решило мою проблему:


Declare 
        v_count NUMBER;

BEGIN


select COUNT(*)
        INTO v_count
        FROM HUB_SEGMENTS
        WHERE APP_OR_REJECT is not null; --for each row where %new.columnname is not new --=> this would be far less "expensive" sql query, need to figure out how to syntax this 

IF v_count >0
        THEN

                 INSERT INTO
                 HUB_APPROVED (HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE)
                 SELECT 
                 HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE 
                 FROM 
                 HUB_SEGMENTS WHERE APP_OR_REJECT = 'APPROVED';


        INSERT INTO 
         HUB_REJECTED (HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE)
         SELECT 
         HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE 
         FROM 
         HUB_SEGMENTS WHERE APP_OR_REJECT = 'REJECTED';     

DELETE
FROM
    "TESTDEMO".HUB_SEGMENTS
WHERE
    APP_OR_REJECT = 'APPROVED' or APP_OR_REJECT = 'REJECTED';

    DBMS_OUTPUT.PUT_LINE('Trigger: Insert to action Tables Executed');

ELSE 
    DBMS_OUTPUT.PUT_LINE('Trigger: Insert to action Tables NOT executed');    

END IF;


end;

Это удалось для того, чего я пытался достичь (не переходя к операторам Insert / Delete, если только на самом деле в определенном столбце c были данные, чтобы во избежание случайного отключения других триггеров (странно)

Коллега сказал мне, что я делаю что-то вроде "для каждой строки, где% new .columnname не является новым => ... "будет гораздо менее интенсивным sql запросом процессора, но мне нужно выяснить, как синтаксис этого. На данный момент приведенный выше код работает в PL / SQL, указывающем на базу данных oracle в DBVis.

Если я найду способ "для каждой строки ...", я опубликую его здесь как комментарий

...