Процедура pl / SQL для генерации значений в одной таблице из значений в другой таблице - PullRequest
0 голосов
/ 27 марта 2019

Я изучаю PL / SQL и не знаю, с чего начать написание процедуры.

У меня есть две таблицы, одна с названием отдела, диапазон идентификаторов от и диапазон идентификаторов до.И еще одна таблица, которая должна иметь все значения в этих диапазонах.

-- table_a
CREATE TABLE table_a (
    D_ID number not null primary key,
    DEPT VARCHAR(10),
    ID_FROM VARCHAR(7),
    ID_TO VARCHAR(7),
    IS_POP varchar(1) check(IS_POP IN ('Y', 'N'))
    );

--values in table a
INSERT INTO table_a values (1, 'abc', 'A10', 'A100', 'Y');
INSERT INTO table_a values (2, 'def', 'B10', 'B50', 'N');
INSERT INTO table_a values (3, 'ghi', 'C01', 'C25', 'N');

--table_b
CREATE TABLE table_b (
    D_id number,
    ID_NUM VARCHAR(7) primary key,
    STATUS VARCHAR(8) CHECK (status IN ('Free','Taken')),
    CONSTRAINT fk_interval FOREIGN KEY (D_id) REFERENCES table_a (D_ID)
    );

Я пытаюсь написать процедуру, чтобы заполнить table_b значениями, сгенерированными из table_a, где поле IS_POP имеет значение «N», и изменить его на «Y» при создании значений.Поэтому в table_b должны быть записи с 66 строками, например,

D_id ID_NUM STATUS
2     B10   Free
2     B11   Free
2     B12   Free
2     B13   Free
...
3     C24   Free
3     C25   Free

1 Ответ

0 голосов
/ 27 марта 2019

Вот пример процедуры, которая создает 66 записей в данных этого примера, хотя я был не уверен, есть некоторая неопределенность относительно того, требуется ли заполнение нулями в TABLE_B или нет.

Здесь также используется итерация DML, что может обеспечить низкую производительность при использовании в масштабе, и было бы неуместно передавать ситуацию, когда TABLE_A был обновлен после того, как уже был заполнен до TABLE_B. Эти вещи могут быть улучшены по мере необходимости в вашей ситуации.

CREATE OR REPLACE PROCEDURE POPULATE_TAB_B
IS
BEGIN
    FOR POINTER IN
        (SELECT D_ID,
             REGEXP_REPLACE(ID_FROM , '[0-9].*' , NULL)             AS PREFIX,
             LEAST(LENGTH(REGEXP_REPLACE(ID_FROM , '[^0-9]' , NULL)) ,
                   LENGTH(REGEXP_REPLACE(ID_TO , '[^0-9]' , NULL))) AS PAD_LENGTH,
             TO_NUMBER(REGEXP_REPLACE(ID_FROM , '[^0-9]' , NULL))   AS FROM_NUM,
             TO_NUMBER(REGEXP_REPLACE(ID_TO , '[^0-9]' , NULL))     AS TO_NUM
         FROM TABLE_A
         WHERE TABLE_A.IS_POP = 'N' FOR UPDATE NOWAIT)
        LOOP
            INSERT INTO TABLE_B(D_ID , ID_NUM , STATUS)
            SELECT POINTER.D_ID,
                (POINTER.PREFIX || LPAD(TO_CHAR(((LEVEL - 1) + POINTER.FROM_NUM)) , POINTER.PAD_LENGTH , '0')), 'Free'
            FROM DUAL
            CONNECT BY LEVEL <= ((POINTER.TO_NUM + 1) - POINTER.FROM_NUM);

            UPDATE TABLE_A
            SET TABLE_A.IS_POP = 'Y'
            WHERE TABLE_A.D_ID = POINTER.D_ID;

        END LOOP;

END;
/

Procedure created.

BEGIN
    POPULATE_TAB_B();
END;
/

PL/SQL procedure successfully completed.

SELECT *
FROM TABLE_B
ORDER BY 1 ASC, 2 ASC;

 D_ID ID_NUM   STATUS
     2 B10      Free
     2 B11      Free
     2 B12      Free
     2 B13      Free
...
     3 C08      Free
     3 C09      Free
     3 C10      Free
     3 C11      Free
...
     3 C24      Free
     3 C25      Free
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...