[英]Multiple Columns and different Join Conditions for Oracle update
I have 2 tables, 1 is location and the Other one is Look up table.我有 2 个表,1 个是位置,另一个是查找表。 I have to look into the look up table for the location values and if they are present mark them as 'Y' and 'N' along with their corresponding values
我必须查看查找表中的位置值,如果它们存在,则将它们标记为“Y”和“N”以及它们对应的值
I have written individual update Statements as below:我写了如下的个人更新声明:
**Location1,L1value**
Update Location
set (Location1,L1value) =
(select UPPER(VAlue),'Y' from Location_lookup where trim(Location1)=Location
where exists (select 1 from Location_lookup where trim(Location1)=Location);
commit;
**Location2,value**
Update Location
set (Location2,L2value) =
(select UPPER(VAlue),'Y' from Location_lookup where trim(Location2)=Location
where exists (select 1 from Location_lookup where trim(Location2)=Location);
commit;
Similarly for 3rd flag and value.对于第三个标志和值也是如此。
Is there a way to write single update for all the three conditions?有没有办法为所有三个条件编写单个更新? Reason why I am looking for single update is that I have 10+ million records and I do not want to scan the records three different times.
我寻找单个更新的原因是我有 10+ 百万条记录,我不想扫描记录三个不同的时间。 The lookup table has > 32 million records.
查找表有 > 3200 万条记录。
Here is a solution which uses Oracle's bulk FORALL... UPDATE capability.这是一个使用 Oracle 的批量 FORALL... UPDATE 功能的解决方案。 This is not quite as performative as a pure SQL solution but it is simpler to code and the efficiency difference probably won't matter much for 10 million rows on a modern enterprise server, especially if this is a one-off exercise.
这不像纯粹的 SQL 解决方案那样具有性能,但它更易于编码,并且对于现代企业服务器上的 1000 万行,效率差异可能并不重要,特别是如果这是一次性练习。
Points to note:注意事项:
'Y'
setting.'Y'
设置。 I have included processing for 'N'
but see the coda underneath.'N'
处理,但请参阅下面的结尾。declare
cursor get_locations is
with lkup as (
select *
from location_lookup
)
select locn.id
,locn.location1
,upper(lup1.value) as l1value
,nvl2(lup1.value, 'Y', 'N') as l1flag
,locn.location2
,upper(lup2.value) as l2value
,nvl2(lup2.value, 'Y', 'N') as l2flag
,locn.location3
,upper(lup3.value) as l3value
,nvl2(lup3.value, 'Y', 'N') as l3flag
from location locn
left outer join lkup lup1 on trim(locn.location1) = lup1.location
left outer join lkup lup2 on trim(locn.location2) = lup2.location
left outer join lkup lup3 on trim(locn.location3) = lup3.location
where lup1.location is not null
or lup2.location is not null
or lup3.location is not null;
type t_locations_type is table of get_locations%rowtype index by binary_integer;
t_locations t_locations_type;
begin
open get_locations;
loop
fetch get_locations bulk collect into t_locations limit 10000;
exit when t_locations.count() = 0;
forall idx in t_locations.first() .. t_locations.last()
update location
set l1value = t_locations(idx).l1value
,l1flag = t_locations(idx).l1flag
,l2value = t_locations(idx).l2value
,l2flag = t_locations(idx).l2flag
,l3value = t_locations(idx).l3value
,l3flag = t_locations(idx).l3flag
where id = t_locations(idx).id;
end loop;
close get_locations;
end;
/
There is a working demo on db<>fiddle here .这里有一个关于 db<>fiddle的工作演示。 The demo output doesn't exactly match the sample output posted in the query, because that doesn't the given input data.
演示 output 与查询中发布的示例 output 不完全匹配,因为这不是给定的输入数据。
Setting flags to 'Y' or 'N'?将标志设置为“Y”还是“N”?
The code above uses left outer joins on the lookup table.上面的代码在查找表上使用了左外连接。 If a row is found the NVL2() function will return 'Y' otherwise it returns 'N'.
如果找到一行,NVL2() function 将返回“Y”,否则返回“N”。 This means the flag columns are always populated, regardless of whether the value columns are.
这意味着始终填充标志列,无论值列是否存在。 The exception is for rows which have no matches in LOCATION_LOOKUP for any location (
ID=4000
in my demo).例外情况是在任何位置的 LOCATION_LOOKUP 中没有匹配的行(我的演示中的
ID=4000
)。 In this case the flag columns will be null.在这种情况下,标志列将是 null。 This inconsistency follows from the inconsistencies in the question.
这种不一致源于问题中的不一致。
To resolve it:要解决它:
'N'
remove the WHERE clause from the get_locations
cursor query.'N'
填充所有标志列,请从get_locations
查询中删除 WHERE 子句。'N'
change the NVL2() function calls accordingly: nvl2(lup1.value, 'Y', null) as l1flag
'N'
,请相应更改 NVL2() function 调用: nvl2(lup1.value, 'Y', null) as l1flag
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.