2016-12-02 3 views
1

Я пытаюсь обновить все столбцы типа NVARCHAR2 до некоторой случайной строки в моей базе данных. Я повторил все столбцы в базе данных типа nvarchar2 и выполнил инструкцию по обновлению для каждого столбца.Oracle: обновление нескольких столбцов с помощью динамического запроса

for i in (
    select 
     table_name, 
     column_name 
    from 
     user_tab_columns 
    where 
     data_type = 'NVARCHAR2' 
    ) loop 
execute immediate 
    'update ' || i.table_name || 'set ' || i.column_name || 
    ' = DBMS_RANDOM.STRING(''X'', length('|| i.column_name ||')) 
    where ' || i.column_name || ' is not null'; 

Вместо того, чтобы оператор обновления для каждого столбца типа NVARCHAR2, я хочу, чтобы обновить все NVARCHAR столбцы определенной таблицы с помощью одного оператора обновления для эффективности (то есть, один оператор обновления за 1 таблицы) , Для этого я попытался объединить все столбцы nvarchar в таблице во временное хранилище. Но я застрял в написании динамического оператора обновления для этого. Не могли бы вы мне помочь? Заранее спасибо!

+0

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

+0

Добавление столбцов в «SET» - это место, где я застрял. Невозможно записать выбор внутри набора. Есть ли у вас какие-либо идеи о том, как добавить? – rav

+0

Создайте обновление со строкой, добавьте к ней, затем выполните немедленную строку. – OldProgrammer

ответ

1

Пожалуйста, попробуйте следующее:

DECLARE 
    CURSOR CUR IS 
     SELECT 
      TABLE_NAME, 
      LISTAGG(COLUMN_NAME||' = DBMS_RANDOM.STRING(''X'', length(NVL('|| 
      COLUMN_NAME ||',''A''))',', ') 
      WITHIN GROUP (ORDER BY COLUMN_ID) COLUMN_NAME 
     FROM DBA_TAB_COLUMNS 
     WHERE DATA_TYPE = 'NVARCHAR2' 
     GROUP BY TABLE_NAME; 
    TYPE TAB IS TABLE OF CUR%ROWTYPE INDEX BY PLS_INTEGER; 
    T TAB; 
    S VARCHAR2(4000); 
BEGIN 
    OPEN CUR; 
    LOOP 
     FETCH CUR BULK COLLECT INTO T LIMIT 1000; 
     EXIT WHEN T.COUNT = 0; 
     FOR i IN 1..T.COUNT LOOP 
      S := 'UPDATE ' || T(i).TABLE_NAME || ' SET ' || T(i).COLUMN_NAME; 
      EXECUTE IMMEDIATE S; 
     END LOOP; 
    END LOOP; 
    COMMIT; 
END; 
/
+0

@ NVV часть должна заботиться о нулевых значениях в многоколоночном обновлении. Если вам это не подходит, вам нужно сделать это один за другим. никакой другой не идет. – GurV

+0

Спасибо за усилие. Оценил! – rav

+0

'' 'A' '))' '->' '' A ''))) ''. Добавьте аналоговый фильтр 'where colname is not null', пожалуйста. –

1

Я думаю, что бы это сделать. Но, как я сказал в комментариях, вам нужно проверить синтаксис, так как у меня нет экземпляра Oracle для его проверки.

for i in (
    select table_name, 
      'update || i.table_name || set ' || 
      listagg(column_name || '= NLV(' || column_name || ', ' 
       || 'DBMS_RANDOM.STRING(''X'', length('|| column_name ||')))' 
       || ';' 
      ) WITHIN GROUP (ORDER BY column_name) as updCommand 
    from user_tab_columns 
    where DATA_TYPE = 'NVARCHAR2' 
    group by table_name 
) loop 

    execute immediate i.updCommand; 

end loop; 

Если вы нашли какую-либо ошибку, дайте мне знать в комментариях, чтобы я мог ее исправить.

+0

'in group' отсутствует –

+0

Отчет об ошибке - Ошибка SQL: ORA-02000 : missing Ключевое слово WITHIN 02000. 00000 - "missing% s keyword" – rav

+0

@rav Исправлено. Попробуйте сейчас, пожалуйста. –

2

Вы можете попробовать этот. Однако, в зависимости от вашей таблицы это может быть не самое быстрое решение.

for aTable in (
    select table_name, 
     listagg(column_name||' = nvl2('||column_name||', DBMS_RANDOM.STRING(''XX'', length('||column_name||')), NULL)') WITHIN GROUP (ORDER BY column_name) as upd, 
     listagg(column_name) WITHIN GROUP (ORDER BY column_name) as con 
    from user_tab_columns 
    where DATA_TYPE = 'NVARCHAR2' 
    group by table_name 
) loop 

    execute immediate 
     'UPDATE '||aTable.table_name || 
     ' SET '||aTable.upd || 
     ' WHERE COALESCE('||aTable.con||') IS NOT NULL'; 

end loop; 

Результирующей UPDATE (проверьте с DBMS_OUTPUT.PUT_LINE(..)) должна выглядеть следующим образом:

UPDATE MY_TABLE SET 
    COL_A = nvl2(COL_A, DBMS_RANDOM.STRING('XX', length(COL_A)), NULL), 
    COL_B = nvl2(COL_B, DBMS_RANDOM.STRING('XX', length(COL_B)), NULL) 
WHERE COALESCE(COL_A, COL_B) IS NOT NULL;