我在架构abc中有3个表。它们是
user_data
user_addr
用户sal
在其他模式xyz中也可以使用相同的3个表。我们需要将xyz模式表合并为abc模式表。但条件是:
1)如果不存在用户ID,则插入。 2)如果userid已经存在并且其电子邮件ID不同,则插入记录,但在所有3个表中使用seq.next_value更新user_id。
例如:
在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中的最终输出是。如果序列的下一个值是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行。请提出如何获取此记录的建议。我们可以将架构abc中的xyz表作为xyz.user_data访问。
答案 0 :(得分:0)
您可以尝试以下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;
答案 1 :(得分:0)
仅使用SQL的方法
由于对CURRVAL和NEXTVAL的限制,例如它们不能与DISTINCT,子查询或UNION等一起使用(请参见documentation),使用SQL解决问题有些棘手。这是一个使原始表保持完整的解决方案(经过Oracle 12c和11g测试)。步骤:
{1}通过联接“表集”的所有3个表来创建表(称为TEMP_),分别在结果表T1和T2中标记每一行。 UNION结果集。
{2}创建SEQUENCE。
{3}创建MASTER_表,其中包含每个唯一ID(第一次查询)的{a}行和ID多次出现的{b}行,并在NEWID列中填充序列中的值(以100000开始)这个例子)。
{4}通过从MASTER_中选择适当的列来创建3个新的明细表。
整理一下:放下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}查找唯一ID(不需要.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}找到重复的ID,然后按顺序替换。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}用来自MASTER_的数据填充新的“ part”表。
-- 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}创建表“第二组”的副本,{2}创建所需的序列,{3}编写并执行更新已复制副本的过程{4}通过为“表集1”中的每个表编写并执行UNION来创建3个新表,并将它们与“表集2”中对应的(复制的)更新表结合起来,从而创建3个新表是。
-{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
注释作者:这里没有BULK或FORALL操作...我们知道:此过程代码并不像它可能那样有效。但是,PL / SQL代码应该“足够快”,因为我们只处理数千行(每个表)。