объединить две таблицы схем, включая зависимые таблицы, также в Oracle - PullRequest
0 голосов
/ 27 февраля 2019

У меня есть 3 таблицы в схеме abc.The:

user_data

user_addr

user sal

Те же 3 таблицы доступны в другой схеме xyz также. Нам нужно объединить таблицы схемы xyz в таблицы схемы abc. Но условие:

1) если идентификатор пользователя не существует, вставьте.2) если идентификатор пользователя уже существует и его электронный адрес отличается, вставьте запись, но обновите user_id с seq.next_value во всех 3 таблицах.

Например:

В схеме Abc:

таблица user_date

user_id  name     email_id           date
1        gaurav    gav@gmail.com      21-01-2018

таблица user_add

user_id  addres       pin
1        GZB          325123

таблица use_sal

user_id   sal    effective date
1         25000   22-05-2018

В XYZschema:

таблица user_date

user_id  name     email_id           date
1        Arun arun@gmail.com      25-01-2018
5        kk    kk@gmail.com       26-06-2018

таблица user_add

user_id  addres       pin
1        Noida        789546
5        HYD          564231

таблица use_sal

user_id   sal    effective date
1         35000   22-06-2018
5         45000   25-07-2018

Итак, мне нужен окончательный вывод в схеме abc is.Если следующее значение последовательности равно 100, то

таблица user_date

user_id  name     email_id           date
1        gaurav    gav@gmail.com      21-01-2018
5        kk       kk@gmail.com       26-06-2018
100      Arun     arun@gmail.com      25-01-2018

таблица user_add

user_id  addres       pin
1        GZB          325123
5        HYD          564231
100      Noida        789546

таблица use_sal

user_id   sal    effective date
1         25000   22-05-2018
5         45000   25-07-2018
100       35000   22-06-2018

Я только что привел пример нескольких записей. У меня 1000 строк втаблицы. Пожалуйста, предложите, как получить это.Мы можем получить доступ к таблице xyz в схеме abc как xyz.user_data.

Ответы [ 2 ]

0 голосов
/ 02 марта 2019

Подход только для SQL

Из-за ограничений на CURRVAL и NEXTVAL, например, их нельзя использовать с DISTINCT, или в подзапросе, или в UNION и т. Д. (См. документация ) решить проблему с помощью SQL немного сложно.Вот решение, которое оставляет исходные таблицы нетронутыми (протестировано с Oracle 12c и 11g).Шаги:

{1} Создайте таблицу (называемую TEMP_), СОЕДИНЯЯ все 3 таблицы «набора таблиц», пометьте каждую строку в итоговой таблице T1 и T2 соответственно.UNION наборы результатов.

{2} Создайте SEQUENCE.

{3} Создайте таблицу MASTER_, содержащую {a} строк для каждого уникального идентификатора (первый запрос) и {b} строк, чьиидентификаторы встречаются более одного раза, причем столбец NEWID заполняется значениями из последовательности (начиная с 100000 в этом примере).

{4} Создайте 3 новые таблицы сведений, выбрав соответствующие столбцы из MASTER _.

Убирать: сбрасывать TEMP_ и MASTER_

- {1}

-- table TEMP_ contains unaltered data from _both_ table sets ( 2 x 3 tables )
-- multiple ID columns removed
-- short names for the original tables: 
-- ud -> user_data, ua -> user_addr, us -> user_sal
--
create table temp_
as
select 'TS1' as table_set
, ud1.user_id, ud1.name, ud1.email_id, ud1.date_
, ua1.address, ua1.pin
, us1.sal, us1.effective_date
from ud1 
  join ua1 on ud1.user_id = ua1.user_id 
  join us1 on ud1.user_id = us1.user_id 
union
select 'TS2' as table_set
, ud2.user_id, ud2.name, ud2.email_id, ud2.date_
, ua2.address, ua2.pin
, us2.sal, us2.effective_date
from ud2 
  join ua2 on ud2.user_id = ua2.user_id 
  join us2 on ud2.user_id = us2.user_id 
;

- {2}

create sequence uid_seq start with 100000 increment by 1 ;

- {3a}найти уникальные идентификаторы (.NEXTVAL не требуется)

-- column list should be coded (omitted here for clarity)
create table master_ as
select unique_ids.user_id as newid, unique_ids.*
from (
  select table_set
  , user_id, name, email_id, date_  -- table ud
  , address, pin                    -- table ua
  , sal, effective_date             -- table us
  , row_number() over ( partition by user_id order by table_set ) id_occurences
  from temp_ 
) unique_ids
where id_occurences = 1 ;

- {3b} найти дубликаты идентификаторов, заменить их последовательностью. NEXTVAL

-- We cannot use UNION on the 2 resultsets {3a} and {3b} when creating the MASTER_ table,
-- due to the fact that we are using .NEXTVAL (for duplicate user_ids).
-- However, this 2-step approach works. (CTAS, and subsequent INSERT ... SELECT)
-- 
-- column list should be coded (omitted here for clarity)
insert into master_
select uid_seq.nextval as newid, duplicates.*
from (
  select table_set
--  , uid_seq.nextval  -- throws ORA-02287: sequence number not allowed here
  , user_id, name, email_id, date_  -- table ud
  , address, pin                    -- table ua
  , sal, effective_date             -- table us
  , row_number() over ( partition by user_id order by table_set ) id_occurences
  from temp_ 
) duplicates
where id_occurences > 1 
;

- {4} заполнить новыйтаблицы "part" с данными из MASTER_

-- ud: "user_data"
create table udnew 
as 
select newid, name, email_id, date_ from master_ ;

-- ua: "user_add"
create table uanew 
as 
select newid, address, pin from master_ ;

-- us: "use_sal"
create table usnew 
as 
select newid, sal, effective_date from master_ ;

Новые таблицы содержат ...

SQL> select * from udnew ;

     NEWID NAME   EMAIL_ID       DATE_    
---------- ------ -------------- ---------
         1 gaurav gav@gmail.com  21-JAN-18
         5 kk     kk@gmail.com   26-JUN-18
    100000 Arun   arun@gmail.com 25-JAN-18

SQL> select * from uanew ;

     NEWID ADDRE        PIN
---------- ----- ----------
         1 GZB       325123
         5 HYD       564231
    100000 Noida     789546

SQL> select * from usnew ;

     NEWID        SAL EFFECTIVE
---------- ---------- ---------
         1      25000 22-MAY-18
         5      45000 25-JUL-18
    100000      35000 22-JUN-18

Данные испытаний и более подробную информацию: см. Dbfiddle

Альтернативный подход: использовать SQL и PL / SQL

При использовании PL / SQL мы могли бы сделать следующее: {1} создать копии "второго набора" of таблиц, {2} создать требуемую последовательность, {3} написать и выполнить процедуру, которая ОБНОВЛЯЕТ скопированную таблицу, используя .NEXTVALs, где это необходимо. {4} Создайте 3 новые таблицы, написав и выполнив UNION для каждой из таблиц в "набор таблиц 1 ", объединяя их с соответствующими (скопированными) обновленными таблицами" набора таблиц 2 ".

- {1} создает копии" второго набора "таблиц

create table ud2copy as select * from ud2 ;
create table ua2copy as select * from ua2 ;
create table us2copy as select * from us2 ;

- {2} создать требуемую последовательность

create sequence uid_seq start with 100000 increment by 1 ;

- {3} для ОБНОВЛЕНИЯ скопированных таблиц необходимыми .NEXTVALS

create or replace procedure updateIDs
is
begin
  for rec_ in (
    select uid_seq.nextval new_id, ud2copy.user_id
    from ud1 
      join ud2copy on ud1.user_id = ud2copy.user_id 
    where ud1.email_id <> ud2copy.email_id
  )
  loop
    update ud2copy set user_id = rec_.new_id where user_id = rec_.user_id ;
    update ua2copy set user_id = rec_.new_id where user_id = rec_.user_id ;
    update us2copy set user_id = rec_.new_id where user_id = rec_.user_id ;
  end loop;
end ;
/

begin
  updateIDs ;
  commit ;
end ;
/

-{4} создать 3 новые таблицы

create table udnew as select * from ud1 union select * from ud2copy ;
create table uanew as select * from ua1 union select * from ua2copy ;
create table usnew as select * from us1 union select * from us2copy ;

Результат: новые таблицы содержат ...

SQL> select * from udnew ;

   USER_ID NAME   EMAIL_ID       DATE_    
---------- ------ -------------- ---------
         1 gaurav gav@gmail.com  21-JAN-18
         5 kk     kk@gmail.com   26-JUN-18
    100000 Arun   arun@gmail.com 25-JAN-18

SQL> select * from uanew ;

   USER_ID ADDRE        PIN
---------- ----- ----------
         1 GZB       325123
         5 HYD       564231
    100000 Noida     789546

SQL> select * from usnew ;

   USER_ID        SAL EFFECTIVE
---------- ---------- ---------
         1      25000 22-MAY-18
         5      45000 25-JUL-18
    100000      35000 22-JUN-18

Dbfiddle здесь.

Авторы комментариев: здесь нет операций BULK или FORALL ... мы знаем: этот код процедуры не так эффективен, как мог бы.Однако код PL / SQL должен быть «достаточно быстрым», поскольку мы имеем дело только с несколькими тысячами строк (на таблицу).

0 голосов
/ 01 марта 2019

Вы можете попробовать следующий блок PL / SQL

DECLARE 
    l_user user_data.user_id%TYPE;
    l_email user_data.email_id%TYPE;
BEGIN
  FOR i IN (SELECT d.user_id,d.name,d.email_id,d.jdate,a.addr,a.pin,s.sal,s.eff_date 
            FROM xyz.user_data d
            INNER JOIN xyz.user_addr a
            ON d.user_id=a.user_id
            INNER JOIN xyz.user_sal s
            ON d.user_id=s.user_id)
  LOOP
     BEGIN
        SELECT user_id,email_id
          INTO l_user,l_email
          FROM abc.user_data
         WHERE user_id=i.user_id;
     EXCEPTION
     WHEN NO_DATA_FOUND THEN
        l_user := NULL;
        l_email := NULL;
     END;
     IF l_user IS NULL THEN
         INSERT INTO abc.user_data VALUES
         (i.user_id,i.name,i.email_id,i.jdate);

         INSERT INTO abc.user_addr VALUES
         (i.user_id,i.addr,i.pin);

         INSERT INTO abc.user_sal VALUES
         (i.user_id,i.sal,i.eff_date);

     ELSIF l_user IS NOT NULL AND l_email != i.email_id THEN

        SELECT abc.userid.NEXTVAL INTO l_user FROM DUAL;

         INSERT INTO abc.user_data VALUES
         (l_user,i.name,i.email_id,i.jdate);

         INSERT INTO abc.user_addr VALUES
         (l_user,i.addr,i.pin);

         INSERT INTO abc.user_sal VALUES
         (l_user,i.sal,i.eff_date);
     END IF;
  END LOOP;
END;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...