Вспомните опыт обновления данных Oracle

В критический момент доставлен в кратчайшие сроки

Вспомните опыт обновления данных Oracle

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

Тематическое содержание

В базе данных Oracle имеется пакет таблиц (более 1000), и указанные символы некоторых полей в таблицах необходимо изменить на другие указанные символы. Имена таблиц похожи, например TABLE0001, TABLE0002, TABLE0003 и т. Д., Но имена таблиц не являются непрерывными. Таблицы TABLE0100, TABLE0200, TABLE0300 и т. Д. Могут отсутствовать. Имена полей похожи, например FIELD001, FIELD002, FIELD003 и так далее. Имена полей таблицы не фиксированы, некоторые могут иметь только одно поле, некоторые могут иметь более 100 полей, а некоторые таблицы могут не содержать данных. Теперь необходимо изменить содержимое всех полей в этих таблицах, которые содержат символы «Чжан Сан» на «Ли Си», а остальные символы в полях остаются неизменными, например: «Чжан Сан - хороший ученик». к «Ли Си хорошо учится».

Увидев такую ​​проблему, первый способ, который приходит в голову, - написать курсор, чтобы он выполнялся многократно. Но по мере того как я углубился, я обнаружил, что все не так просто. (Если вы хотите увидеть ответ, вы можете перейти к части кода в конце статьи) Вопрос разбит следующим образом:

Проблема прерывания имени
таблицы Имя таблицы не является непрерывным, чтобы определить, существует ли таблица в базе данных. В настоящее время я думаю найти эти таблицы в системной таблице Oracle USER_TABLES (таблица пользователей), а затем вставить их во временную Таблица.И количество записей в таблице также вставляется вместе, что удобно для фильтрации таблицы с 0 записями и уменьшения количества обновлений содержимого позже.

Оператор запроса выглядит следующим образом:

DECLARE 
CURSOR CURS ISSELECT TABLE_NAME FROM USER_TABLES 
WHERE TABLE_NAME LIKE 'TABLE%';
v_sql VARCHAR2(4000);
BEGIN
    FOR CUR IN CURS LOOP
    v_sql :=' SELECT  '||''CUR.TABLE_NAME''||',COUNT(1) T_CNT
    INTO TEMP_TABLE FROM '||CUR.TABLE_NAME;
    EXECUTE IMMEDIATE v_sql;
    END LOOP;
END;
END;

Жалко, что здесь сообщалось об ошибке. Причина ошибки в том, что я хочу вставить имя таблицы переменных CUR.TABLE_NAME в качестве символа во временную таблицу, чтобы я мог запросить временную таблицу TEMP_TABLE, чтобы напрямую узнать определенное количество записей в каждой таблице, но в динамическом. Оператор SQL неуспешен и может найти только другой способ.

Поместите пройденную таблицу в EXCEL, чтобы автоматически сгенерировать нужный мне оператор запроса, как показано ниже:

Вспомните опыт обновления данных Oracle

Вспомните опыт обновления данных Oracle

Рисунок EXCEL завершает сращивание предложений запроса

Затем запустите выполнение этих объединенных операторов запроса, а затем можно запросить объем данных каждой таблицы и вставить во временную таблицу TEMP_TABLE. Первый шаг успешно выполнен ~


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

Конкретный код выглядит следующим образом:


DECLARE
CURSOR mycur ISSELECT T_NAME 
FROM TEMP_TABLE WHERE T_CNT<>0 ;
myrecord mycur%ROWTYPE;
v_sql1 VARCHAR2(4000);
v_sql2 VARCHAR2(4000);
v_sql3 VARCHAR2(4000);
v_sql4 VARCHAR2(4000);
v_sql5 VARCHAR2(4000);
BEGINOPEN mycur;
LOOP
FETCH mycur INTO myrecord;
EXIT WHEN mycur%NOTFOUND;
v_sql1 :='UPDATE '||myrecord.T_NAME||' SET
FIELD001=REPLACE(FIELD001,''张三'',''李四'')';
v_sql2 :='UPDATE '||myrecord.T_NAME||' SET 
FIELD002=REPLACE(FIELD002,''张三'',''李四'')';
v_sql3 :='UPDATE '||myrecord.T_NAME||' SET 
FIELD003=REPLACE(FIELD003,''张三'',''李四'')';
v_sql4 :='UPDATE '||myrecord.T_NAME||' SET 
FIELD004=REPLACE(FIELD004,''张三'',''李四'')';
v_sql5 :='UPDATE '||myrecord.T_NAME||' SET 
FIELD005=REPLACE(FIELD005,''张三'',''李四'')';
EXECUTE IMMEDIATE v_sql1;
EXECUTE IMMEDIATE v_sql2;
EXECUTE IMMEDIATE v_sql3;
EXECUTE IMMEDIATE v_sql4;
EXECUTE IMMEDIATE v_sql5;
END LOOP;
CLOSE mycur;
END;

Код может выполняться плавно, но в нем обнаружена проблема. Этот столбец не обязательно существует. Если в выполнении нет столбца, обязательно будет сообщено об ошибке. Ошибка базы данных не будет автоматически пропущена для вас, и это остановится. Этого эффекта не добиться!

Дальнейшие изменения
Поскольку этот столбец может не существовать, как насчет того, чтобы я сначала рассудил?

Следуя этой идее, код модифицируется, системная таблица USER_TAB_COLUMNS запрашивается, существует ли определенное имя столбца в обновленной таблице, если оно существует, выполняется обновление, а если оно не существует, оно пропускается.

Конкретный код выглядит следующим образом:

DECLARE
--定义游标
CURSOR mycur IS   
--将临时表TEMP_TABLE中记录数不为0的表查询出来
SELECT T_NAME FROM TEMP_TABLE WHERE T_CNT<>0 ;
myrecord mycur%ROWTYPE;
--定义变量
v_sql1 VARCHAR2(4000);
v_count INTEGER;
--定义列变量,
v_name VARCHAR2(20) := 'TABLE0001';
BEGIN
--打开游标
OPEN mycur;
LOOP
FETCH mycur INTO myrecord;
EXIT WHEN mycur%NOTFOUND;
--从系统表USER_TAB_COLUMNS中查询被更新的表中是否存在定义的列名
SELECT COUNT(*) INTO v_count 
FROM USER_TAB_COLUMNS 
WHERE table_name=myrecord.T_NAME 
and column_name=v_name;
--如果存在执行更新
IF v_count>0 THEN
v_sql1 :='UPDATE '||myrecord.T_NAME||' SET 
'||v_name||'=REPLACE('||v_name||',''张三'',''李四'')';
EXECUTE IMMEDIATE v_sql1;
END IF;
END LOOP;
--结束游标
CLOSE mycur;
END;

Результат успешный, вам нужно только изменить переменную v_name. Это очень быстро выполняется один раз и занимает всего около 7 секунд.


Последний шаг последующей оптимизации может быть полностью автоматизирован, то есть поместить все столбцы в таблицу и выполнить курсор в цикле, при условии, что вы знаете, сколько столбцов самые большие, или вы можете напрямую взять максимальное значение FIELD999. , который может сравниваться во время выполнения. Это требует много времени, потому что каждый раунд он должен 999 раз определять, существует ли столбец.

На данный момент функция исправления и изменения содержимого некоторых полей в пакетном режиме завершена.

Небольшие размышления
побудили меня задуматься над этой темой, как хорошими, так и плохими.

Хорошо, что если вы столкнетесь с проблемой, которую можно решить другими способами, не вешайте ее на дерево, первый шаг не найден. Если вы потратите все свое время на этот шаг, он определенно перевесит выгоду. В работе важнее эффективность.Если вы можете использовать другие методы для решения проблемы, вы можете изменить метод как можно скорее. Кроме того, уточнение проблемы может сделать мышление более логичным.

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

Заключение Вы
неизбежно столкнетесь с некоторыми проблемами на работе и в жизни.Когда вы можете создать проблему или вещь с помощью собственного мышления, чувство выполненного долга самоочевидно. Может, в этом и счастье программистов!

рекомендация

отblog.51cto.com/15057820/2656423
рекомендация