Хранимая процедура и курсор Oracle - PullRequest
0 голосов
/ 20 мая 2018

Я пытаюсь написать хранимую процедуру для преобразования этого:

|----------|----------|----------|----------|----------|
|    ID    |   ESD    |  TD      |   IS_DB  | TEST_SET |
|----------|----------|----------|----------|----------|
|    1     |  10      |  20      |    1     |    2     |
|    2     |  30      |  (null)  |    1     |    2     |
|    3     |  40      |  (null)  |    1     |    2     |
|    4     |  50      |  60      |    0     |    2     |
|    5     |  (null)  |  70      |    1     |    2     |
|    6     |  75      |  100     |    1     |    2     |
|    7     |  (null)  |  80      |    1     |    2     |
|----------|----------|----------|----------|----------|

в следующее:

|----------|----------|
|  DT      |  FLAG    |
|----------|----------|
|  10      |  E       |
|  20      |  H       |
|  30      |  E       |
|  40      |  E       |
|  50      |  E       |
|  60      |  S       |
|  70      |  H       |
|  75      |  E       |
|  80      |  H       |
|  100     |  H       |
|----------|----------|

Бизнес-правила:

Для каждогострока в TEST_DATA_SOVLP:

  1. Если текущее значение ESD не равно null, то:

    • вставить строку в TEMP со значениями: <ESD value>, E
  2. Если текущее значение TD не null, то:

    • Если IS_DB=0=> вставить в ТЕМП значения: <TD value>, S
    • Если IS_DB=1 => вставить в ТЕМП значения: <TD value>, H

но я не получаю ничего похожего на то, что ожидал:

  • Ничего не пишется в таблице TEMP.
  • Значения отображения консолиэто не имеет смысла для меня:

    20 H 10 E 20 H 10 E 20 H ...

Вопросы :

  1. Может кто-нибудь сказать мне, что я делаю неправильно в моем процессе?

  2. Почему в TEMP не хранятся данные?

  3. Что может быть более чистым способом решения этой проблемы?Я попытался использовать запрос SQL (см. здесь ), но безуспешно.Примечание: у меня есть несколько похожих процедур для записи, которые я хотел бы затем вызвать из «основного» процесса, который суммирует логику.

Спасибо

1.Таблица с некоторыми данными

CREATE TABLE "TEST_DATA_SOVLP" 
   (    "ID" NUMBER,
   "ESD" NUMBER, 
    "TD" NUMBER, 
    "IS_DB" NUMBER(1,0) DEFAULT 0, 
    "TEST_SET" NUMBER
   )

Некоторые данные

INSERT INTO "TEST_DATA_SOVLP" (ID, ESD, TD, IS_DB, TEST_SET) VALUES ('1', '10', '20', '1', '2');
INSERT INTO "TEST_DATA_SOVLP" (ID, ESD, IS_DB, TEST_SET) VALUES ('2', '30', '1', '2');
INSERT INTO "TEST_DATA_SOVLP" (ID, ESD, IS_DB, TEST_SET) VALUES ('3', '40', '1', '2');
INSERT INTO "TEST_DATA_SOVLP" (ID, ESD, TD, IS_DB, TEST_SET) VALUES ('4', '50', '60', '1', '2');
INSERT INTO "TEST_DATA_SOVLP" (ID, TD, IS_DB, TEST_SET) VALUES ('5', '70', '1', '2');
INSERT INTO "TEST_DATA_SOVLP" (ID, ESD, TD, IS_DB,TEST_SET) VALUES ('6', '75', '100', '1', '2');
INSERT INTO "TEST_DATA_SOVLP" (ID, TD, IS_DB, TEST_SET) VALUES ('7', '80', '1', '2');

2.Таблица для хранения результатов

  CREATE TABLE "TEMP" 
   (    "DT" NUMBER, 
    "FLAG" VARCHAR2(1 BYTE)
   ) 

3.PL / SQL манипулирование данными и сохранение результатов

CREATE OR REPLACE PROCEDURE S_OVLP 

AS 

   CURSOR cSH IS
      SELECT ID, ESD, TD, IS_DB, TEST_SET
      FROM TEST_DATA_SOVLP
      WHERE TEST_SET = 2;

    rec_csh cSH%ROWTYPE;

BEGIN

 -- DBMS_UTILITY.EXEC_DDL_STATEMENT('TRUNCATE TABLE TEMP');

  OPEN cSH;    

    LOOP

        FETCH cSH INTO rec_csh;
        EXIT WHEN cSH%NOTFOUND;

        IF rec_csh.esd IS NOT NULL THEN
            INSERT INTO TEMP VALUES (rec_csh.esd, 'E');
            dbms_output.put_line(rec_csh.esd || ' E');
        END IF;

        IF rec_csh.td IS NOT NULL THEN 
            IF rec_csh.is_db = 1 THEN     
                INSERT INTO TEMP VALUES (rec_csh.td, 'H');
                dbms_output.put_line(rec_csh.td || ' H');
            ELSE
                INSERT INTO TEMP VALUES (rec_csh.td, 'S');
                dbms_output.put_line(rec_csh.td || ' S');
            END IF;
        END IF;

    END LOOP;

  CLOSE cSH;

END S_OVLP;

Ответы [ 3 ]

0 голосов
/ 20 мая 2018

Просто запустите INSERT INTO, процедура не нужна.

INSERT INTO temp 
SELECT esd, 
       'E' 
FROM   test_data_sovlp 
WHERE  esd IS NOT NULL 
  UNION ALL 
SELECT td, 
       CASE is_db 
         WHEN 0 THEN 'S' 
         WHEN 1 THEN 'H' 
       END AS FLAG 
FROM   test_data_sovlp 
WHERE  td IS NOT NULL 

Демо

0 голосов
/ 20 мая 2018

Судя по вашим бизнес-правилам, вы можете сделать это просто с двумя вставками, например:

insert into temp
select esd, 'E' from TEST_DATA_SOVLP where test_set=2 and esd is not null;

insert into temp
select td, decode(is_db, 1, 'H', 'S') from TEST_DATA_SOVLP 
     where test_set=2 and td is not null;

Помимо условий на esd и td, селекторы также «встраивают»условие на test_set, заданное курсором в вашей процедуре.

decode сравнивает is_db с 1, а если совпадает, используйте 'H', в противном случае используется 'S' (так что 2 дасттот же результат, что и 0, но я полагаю, что вам нужно проверить свои данные, поскольку вы определили, что давать только для 1 или 0).

О процедуре

Я проверял еена https://livesql.oracle.com и вывод выглядит нормально:

10 E
20 H
30 E
40 E
50 E
60 H
70 H
75 E
100 H
80 H

(таблица содержит все is_db = 1, см. вставки, которые вы указали в вопросе).

Кроме того,temp таблица заполняется соответственно.Таким образом, проблема не может быть воспроизведена, и ваша первоначальная процедура работает нормально, как и ожидалось.

0 голосов
/ 20 мая 2018

Что ж, я наконец-то понял все правильно с приведенным ниже кодом, изменив вложенный оператор IF.Но я очень разочарован тем, как работает PL / SQL.

CREATE OR REPLACE PROCEDURE S_OVLP 

AS 

   CURSOR cSH IS
      SELECT ID, ESD, TD, IS_DB, TEST_SET
      FROM TEST_DATA_SOVLP
      WHERE TEST_SET = 2;

    rec_csh cSH%ROWTYPE;

BEGIN

  DBMS_UTILITY.EXEC_DDL_STATEMENT('TRUNCATE TABLE TEMP');

  OPEN cSH;    

    LOOP

        FETCH cSH INTO rec_csh;
        EXIT WHEN cSH%NOTFOUND;

        IF rec_csh.esd IS NOT NULL THEN
            INSERT INTO TEMP VALUES (rec_csh.esd, 'E');
            dbms_output.put_line(rec_csh.esd || ' E');
        END IF;

        IF rec_csh.td IS NULL THEN 
            CONTINUE;
        END IF;

        IF rec_csh.is_db = 1 THEN     
            INSERT INTO TEMP VALUES (rec_csh.td, 'H');
            dbms_output.put_line(rec_csh.td || ' H');
        ELSE
            INSERT INTO TEMP VALUES (rec_csh.td, 'S');
            dbms_output.put_line(rec_csh.td || ' S');
        END IF;

    END LOOP;

  CLOSE cSH;

END S_OVLP;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...