Использование переменной с Substr в PLSQL - PullRequest
0 голосов
/ 26 июня 2019

Я пытаюсь использовать переменную, чтобы установить длину команды substr. Если я явно установлю скажем 0,13, то код работает нормально, однако я хочу иметь возможность использовать переменную.

В конце кода находится область вопроса:

: new.DOCNO: = substr (: new.DESCRIP, 0,15); - успех ... но ограничен

: new.DOCNO: = substr (: new.DESCRIP, 0, n_len); - ошибка

Код в целом ищет номер шаблона из имени файла и помещает его в другой столбец.

Пример: HR_1000-0001_A Это файл.pdf

Я пробовал разные типы данных: целое число, число и т. Д. Код компилируется, но происходит сбой при запуске триггера.

CREATE OR REPLACE TRIGGER set_doc_number
BEFORE UPDATE ON external_doc
FOR EACH ROW
WHEN (
    new.STATUS = 'Released'
    -- current document# is either '' or is ONLY a number
    AND (
            new.DOC_LIBRARY_ID = ''
            OR              
            REGEXP_LIKE(new.DOC_LIBRARY_ID,'(\d+)')
        )
    )
DECLARE 
    -- init variables
    b_update boolean;
    n_len number := 0;
BEGIN
    -- reset for each loop
    b_update := FALSE;

    -- check if criteria is met 

    -- AAA_####-####_AA
    IF b_update = FALSE AND REGEXP_LIKE(:new.DESCRIP,'([A-Z][A-Z][A-Z]_(\d{4})-(\d{4})_[A-Z])') THEN 
        b_update := TRUE;
        n_len := 15;
    END IF;
    -- AA_####-####_AA
    IF b_update = FALSE AND REGEXP_LIKE(:new.DESCRIP,'([A-Z][A-Z]_(\d{4})-(\d{4})_[A-Z])') THEN 
        b_update := TRUE;
        n_len := 14;
    END IF;
    -- AAA_####-####_A
    IF b_update = FALSE AND REGEXP_LIKE(:new.DESCRIP,'([A-Z][A-Z][A-Z]_(\d{4})-(\d{4})_[A-Z])') THEN 
        b_update := TRUE;
        n_len := 15;
    END IF;
    -- AA_####-####_A
    IF b_update = FALSE AND REGEXP_LIKE(:new.DESCRIP,'([A-Z][A-Z]_(\d{4})-(\d{4})_[A-Z])') THEN 
        b_update := TRUE;
        n_len := 14;
    END IF;
    -- AAA_####-####
    IF b_update = FALSE AND REGEXP_LIKE(:new.DESCRIP,'([A-Z][A-Z][A-Z]_(\d{4})-(\d{4}))') THEN  
        b_update := TRUE;
        n_len := 13;
    END IF;
    -- AA_####-####
    IF b_update = FALSE AND REGEXP_LIKE(:new.DESCRIP,'([A-Z][A-Z]_(\d{4})-(\d{4}))') THEN       
        b_update := TRUE;
        n_len := 12;
    END IF;

    -- can we update?
    IF b_update = TRUE THEN
        -- update
        :new.DOCNO := substr(:new.DESCRIP,0,n_len);
    END IF;
END;

1 Ответ

1 голос
/ 26 июня 2019

Я не уверен, почему использование n_len не удается, мне кажется, это нормально. Индексы PL / SQL начинаются с 1, а не с 0, но работают нормально, если вы используете 0, так что это не проблема.

Если вы собираетесь использовать функции регулярного выражения, я бы рекомендовал просто использовать regexp_substr:

CREATE OR REPLACE TRIGGER set_doc_number
BEFORE UPDATE ON external_doc
FOR EACH ROW
WHEN (
    new.STATUS = 'Released'
    -- current document# is either '' or is ONLY a number
    AND (
            new.DOC_LIBRARY_ID = ''
            OR              
            REGEXP_LIKE(new.DOC_LIBRARY_ID,'(\d+)')
        )
    )
DECLARE 
    -- init variables
    v_docno varchar2(20);
BEGIN
    -- look for a str with (2-3 alpha)_####-####(optional underscore and 1-3 alpha)
    v_docno := regexp_substr(:new.DESCRIP,'[A-Z][A-Z][A-Z]?_\d{4}-\d{4}(_[A-Z][A-Z]?[A-Z]?)?');

    -- can we update?
    IF v_docno is not null THEN
        -- update
        :new.DOCNO := v_docno;
    END IF;
END;
...