Перемещение столбца в Oracle Pl / Sql с циклом for - PullRequest
0 голосов
/ 15 мая 2019

Например, я хочу переместить мои 2 столбца между, например, KW_01 (раскрывающийся список) и KW_03 (раскрывающийся список), между значениями KW_04 (раскрывающийся список) и KW_06 (раскрывающийся список). У меня есть 53 столбца в таблице. Я написал код (см. Ниже), но, к сожалению, он не работает должным образом. Он делает это, когда я запускаю код.

Неожиданные результаты:

Outer Loop counter is kw_04 Inner Loop counter is 1
Outer Loop counter is kw_04 Inner Loop counter is 2
Outer Loop counter is kw_04 Inner Loop counter is 3
Outer Loop counter is kw_05 Inner Loop counter is 1
Outer Loop counter is kw_05 Inner Loop counter is 2
Outer Loop counter is kw_05 Inner Loop counter is 3
Outer Loop counter is kw_06 Inner Loop counter is 1
Outer Loop counter is kw_06 Inner Loop counter is 2
Outer Loop counter is kw_06 Inner Loop counter is 3


DECLARE 
  plsql VARCHAR2(500);
BEGIN
  For i in (SELECT column_id
              FROM alsi_bedarfsplanung unpivot(column_value FOR column_id IN("KW_01", "KW_02", "KW_03", "KW_04", "KW_05", "KW_06"))
             WHERE column_id BETWEEN :drp1 AND :drp2
               and id = 1)
  LOOP
    FOR o in (SELECT column_value
                FROM alsi_bedarfsplanung unpivot(column_value FOR column_id IN("KW_01", "KW_02", "KW_03", "KW_04", "KW_05", "KW_06"))
               WHERE column_id BETWEEN :drp3 AND :drp4
                 and id = 1)
    LOOP
      plsql := ' UPDATE ALSI_BEDARFSPLANUNG SET ' || i.column_id || ' = ' ||
               o.column_value || ' where ID = 1 ';
      EXECUTE IMMEDIATE plsql;
    END LOOP;
  END LOOP;
END;

Моя БД

Что я хочу,

Outer Loop counter is kw_04 Inner Loop counter is 1//(KW_1 Value)
Outer Loop counter is kw_05 Inner Loop counter is 2//(KW_2 Value)
Outer Loop counter is kw_06 Inner Loop counter is 3//(KW_3 Value)

1 Ответ

0 голосов
/ 15 мая 2019

Проблема в том, как вы зацикливаетесь внутри цикла;что вам действительно нужно сделать, это определить столбцы для обновления и отдельно, а затем выполнить цикл по каждому набору столбцов для выполнения обновлений.

Еще лучше было бы выполнить всю работу в одном обновлении,например, так:

-- should error with "Invalid columns specified" due to final proc call,
-- but should update the two rows accordingly
DECLARE
  TYPE col_array IS TABLE OF VARCHAR2(30) INDEX BY pls_INTEGER;
  v_cols_to_update_arry col_array;
  v_cols_update_from_arry col_array;
  PROCEDURE update_cols (p_id IN INTEGER,
                         p_drp1 IN VARCHAR2,
                         p_drp2 IN VARCHAR2,
                         p_drp3 IN VARCHAR2,
                         p_drp4 IN VARCHAR2)
  IS
    v_sql CLOB := 'UPDATE alsi_bedarfsplanung SET '||CHR(10);
  BEGIN
    SELECT column_id
    BULK COLLECT INTO v_cols_to_update_arry
    FROM   alsi_bedarfsplanung
    UNPIVOT (column_val FOR column_id IN (kw_01, kw_02, kw_03, kw_04, kw_05, kw_06, kw_07, kw_08))
    WHERE  column_id BETWEEN p_drp1 AND p_drp2
    AND    id = p_id;

    SELECT column_id
    BULK COLLECT INTO v_cols_update_from_arry
    FROM   alsi_bedarfsplanung
    UNPIVOT (column_val FOR column_id IN (kw_01, kw_02, kw_03, kw_04, kw_05, kw_06, kw_07, kw_08))
    WHERE  column_id BETWEEN p_drp3 AND p_drp4
    AND    id = p_id;

    IF v_cols_to_update_arry.count > 0
       AND v_cols_update_from_arry.count > 0
       AND v_cols_to_update_arry.count = v_cols_update_from_arry.count THEN

      FOR i IN 1..v_cols_to_update_arry.count
      LOOP
        if i = 1 then 
          v_sql := v_sql || '  ' || v_cols_to_update_arry(i) || ' = ' || v_cols_update_from_arry(i);
        else
          v_sql := v_sql || ',' || CHR(10) || '  ' || v_cols_to_update_arry(i) || ' = ' || v_cols_update_from_arry(i);
        end if;
      END LOOP;

      v_sql := v_sql || chr(10) || 'where id = :p_id';

      EXECUTE IMMEDIATE v_sql USING p_id;

    ELSE
      raise_application_error(-20001, 'Invalid columns specified');
    END IF;
  END update_cols;
BEGIN
  update_cols (p_id => 1,
               p_drp1 => 'KW_04',
               p_drp2 => 'KW_06',
               p_drp3 => 'KW_01',
               p_drp4 => 'KW_03');

  COMMIT;

  update_cols (p_id => 2,
               p_drp1 => 'KW_05',
               p_drp2 => 'KW_08',
               p_drp3 => 'KW_01',
               p_drp4 => 'KW_04');

  COMMIT;

  update_cols (p_id => 1,
               p_drp1 => 'KW_01',
               p_drp2 => 'KW_02',
               p_drp3 => 'KW_05',
               p_drp4 => 'KW_05');

END;
/

Это работает путем выборки каждого списка столбцов в отдельный массив, циклически перебирая массивы для создания списка обновляемых столбцов, прежде чем объединять его в оператор обновления.

Вот демонстрация того, как это работает

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