2010-04-13 3 views
4

Я пишу процедуру PL/SQL, который загружает некоторые данные из схемы A в схемах B. Они оба очень разные схемы, и я не могу изменить структуру схема B.Преобразование столбцов таблицы ключевых пары значений

Столбцы в различных таблицах на схеме A (объединенные в виде) должны быть вставлены в схему B в виде ключей => пары значений в 2 столбца в таблице, каждая в отдельной строке. Например, первое имя сотрудника может присутствовать как employee.firstname в схеме А, но нужно будет ввести в схеме B, как:

id=>1, key=>'A123', value=>'Smith' 

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

Пример кода:

create table schema_a_employees (
    emp_id number(8,0), 
    firstname varchar2(50), 
    surname varchar2(50) 
); 
insert into schema_a_employees values (1, 'James', 'Smith'); 
insert into schema_a_employees values (2, 'Fred', 'Jones'); 

create table schema_b_values (
    emp_id number(8,0), 
    the_key varchar2(5), 
    the_value varchar2(200) 
); 

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

insert into schema_b_values (1, 'A123', v_firstname); 
insert into schema_b_values (1, 'B123', v_surname); 

То, что я хотел бы быть в состоянии сделать это иметь локальную таблицу поиска в схеме A, в котором перечислены все ключи от схемы B, вместе с колонной, которая дает имя столбца в таблицу в схеме A, которую следует использовать для заполнения, например ключ «A123» в схеме B должен быть заполнен значением столбца «firstname» в схеме A, например.

create table schema_a_lookup (
    the_key varchar2(5), 
    the_local_field_name varchar2(50) 
); 
insert into schema_a_lookup values ('A123', 'firstname'); 
insert into schema_a_lookup values ('B123', 'surname'); 

Но я не знаю, как я мог динамически использовать значение из таблицы поиска, чтобы сообщить Oracle, какие столбцы использовать.

Итак, мой вопрос в том, есть ли элегантное решение для заполнения таблицы schema_b_values ​​данными из schema_a_employees без hardcoding для каждого возможного ключа (то есть A123, B123 и т. Д.)?

Cheers.

+0

+! для утверждения инструкций настройки. Это упростило тестирование решения. – APC

ответ

1

Я искренне надеюсь, что ваша схема B не является dreadedkey-value pair дизайн. Хотя некоторая динамическая таблица значений атрибутов может быть полезна в некоторой ситуации, вы обнаружите, что все, кроме самых простых запросов, практически невозможно записать в EAV-дизайне (даже простой запрос типа «найти всех сотрудников, которых зовут Джон Смит», трудно писать - и невозможно настроить).

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

SQL> INSERT ALL 
    2  INTO schema_b_values VALUES (emp_id, 'A123', firstname) 
    3  INTO schema_b_values VALUES (emp_id, 'B123', surname) 
    4  SELECT emp_id, firstname, surname 
    5  FROM schema_a_employees; 

4 rows inserted 

Вы можете использовать следующий запрос, чтобы сгенерировать заявление:

SQL> SELECT 'INSERT ALL ' sql_lines FROM dual 
    2 UNION ALL 
    3 SELECT 'INTO schema_b_values VALUES (emp_id, ''' 
    4   || dbms_assert.simple_sql_name(the_key) 
    5   || ''', ' 
    6   || dbms_assert.simple_sql_name(the_local_field_name) 
    7   ||')' 
    8 FROM schema_a_lookup 
    9 UNION ALL 
10 SELECT 'SELECT * FROM schema_a_employees' FROM dual; 

SQL_LINES 
-------------------------------------------------------------------------------- 
INSERT ALL 
INTO schema_b_values VALUES (emp_id, 'A123', firstname) 
INTO schema_b_values VALUES (emp_id, 'B123', surname) 
SELECT * FROM schema_a_employees 

Вы можете затем используйте EXECUTE IMMEDIATE или DBMS_SQL для выполнения этого оператора.

+0

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

1

Мне нравится INSERT ALL как подход, потому что он предлагает заключенную транзакцию: либо все строки вставлены, либо нет. Мой опыт миграции данных состоит в том, что он имеет тенденцию быть очень итеративным процессом, поэтому все, что помогает в очистке и регрессии, является отличным благом.

SQL> declare 
    2  l_src_name varchar2(30) := 'SCHEMA_A_EMPLOYEES'; 
    3  l_tgt_name varchar2(30) := 'SCHEMA_B_VALUES'; 
    4  stmt varchar2(32767); 
    5 begin 
    6  for pk_rec in (select cc.table_name, cc.column_name 
    7      from user_cons_columns cc 
    8        , user_constraints c 
    9      where c.table_name = l_src_name 
10      and c.constraint_type = 'P' 
11      and cc.table_name = l_src_name) 
12  loop 
13   stmt := 'insert all'; 
14   for col_rec in (select * from schema_a_lookup) 
15   loop 
16    stmt := stmt||' into '||l_tgt_name||' values (' 
17     ||pk_rec.column_name 
18     ||', '''||col_rec.the_key||''',' 
19     ||col_rec.the_local_field_name 
20     ||')'; 
21   end loop; 
22   stmt := stmt||' select * from '||l_src_name; 
23  end loop; 
24  execute immediate stmt; 
25 end; 
26/

PL/SQL procedure successfully completed. 

SQL> 

Сколько строк?

SQL> select * from schema_b_values; 

    EMP_ID THE_K THE_VALUE 
---------- ----- --------------- 
     1 A123 James 
     2 A123 Fred 
     1 B123 Smith 
     2 B123 Jones 

SQL> 

Я завернул запросы в PL/SQL, потому что он указывает путь к дальнейшей автоматизации. Вы можете добавить таблицу для хранения имен SOURCE и TARGET. Очевидно, что есть возможность для развлечения, если исходная таблица имеет составной первичный ключ.

+0

Ничего, я не думал об использовании словаря данных здесь. –

Смежные вопросы