Sql Oracle update的多列和不同的联接条件

Sql Oracle update的多列和不同的联接条件,sql,oracle,sql-update,bulk-operations,Sql,Oracle,Sql Update,Bulk Operations,我有两个表,一个是位置表,另一个是查找表。我必须查看查找表中的位置值,如果它们存在,则将它们标记为“Y”和“N”,以及相应的值 我已编写了如下个人更新声明: **Location1,L1value** Update Location set (Location1,L1value) = (select UPPER(VAlue),'Y' from Location_lookup where trim(Location1)=Location where exists (select 1 f

我有两个表,一个是位置表,另一个是查找表。我必须查看查找表中的位置值,如果它们存在,则将它们标记为“Y”和“N”,以及相应的值

我已编写了如下个人更新声明:

**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;
第三个标志和值也是如此


有没有一种方法可以为所有三种情况编写一次更新?我寻找单一更新的原因是我有1000多万条记录,我不想扫描记录三次。查找表有超过3200万条记录。

这里有一个解决方案,该解决方案使用Oracle的大容量存储。。。更新能力。这并不像纯SQL解决方案那样具有很高的性能,但它更易于编码,而且对于现代企业服务器上的1000万行来说,效率差异可能不会有多大影响,特别是如果这是一次性的操作

注意事项:

  • 您不会说位置是否有主键。对于这个答案,我假设它有一个ID列。如果没有主键,解决方案将不起作用,但如果表没有主键,则可能会遇到更大的问题
  • 您的问题提到将标志列设置为“Y”和“N”,但所需的输出仅显示
    'Y'
    设置。我已经包括了
    'N'
    的处理,但是可以看到下面的尾声
  • 有一个工作演示。演示输出与查询中发布的示例输出不完全匹配,因为这与给定的输入数据不匹配


    将标志设置为“Y”或“N”?

    上面的代码在查找表上使用左外部联接。如果找到一行,NVL2()函数将返回“Y”,否则返回“N”。这意味着无论值列是否为空,都将始终填充标志列。例外情况是在任何位置的位置查找中没有匹配项的行(
    ID=4000
    ,在我的演示中)。在这种情况下,标志列将为null。这种不一致性源于问题中的不一致性

    要解决这个问题:

    • 如果希望用
      'N'
      填充所有标志列,请从
      get\u locations
      光标查询中删除WHERE子句
    • 如果不想将标志设置为
      'N'
      则相应地更改NVL2()函数调用:
      NVL2(lup1.value,'Y',null)为l1flag

    这里有一个解决方案,它使用Oracle的大容量解决所有。。。更新能力。这并不像纯SQL解决方案那样具有很高的性能,但它更易于编码,而且对于现代企业服务器上的1000万行来说,效率差异可能不会有多大影响,特别是如果这是一次性的操作

    注意事项:

  • 您不会说位置是否有主键。对于这个答案,我假设它有一个ID列。如果没有主键,解决方案将不起作用,但如果表没有主键,则可能会遇到更大的问题
  • 您的问题提到将标志列设置为“Y”和“N”,但所需的输出仅显示
    'Y'
    设置。我已经包括了
    'N'
    的处理,但是可以看到下面的尾声
  • 有一个工作演示。演示输出与查询中发布的示例输出不完全匹配,因为这与给定的输入数据不匹配


    将标志设置为“Y”或“N”?

    上面的代码在查找表上使用左外部联接。如果找到一行,NVL2()函数将返回“Y”,否则返回“N”。这意味着无论值列是否为空,都将始终填充标志列。例外情况是在任何位置的位置查找中没有匹配项的行(
    ID=4000
    ,在我的演示中)。在这种情况下,标志列将为null。这种不一致性源于问题中的不一致性

    要解决这个问题:

    • 如果希望用
      'N'
      填充所有标志列,请从
      get\u locations
      光标查询中删除WHERE子句
    • 如果不想将标志设置为
      'N'
      则相应地更改NVL2()函数调用:
      NVL2(lup1.value,'Y',null)为l1flag

    我的错。我已将第二个查询更新为指向右侧列(位置2)。查找有32个以上的密耳记录。位置1、位置2、位置3将在查找表My bad的位置列中匹配。我已将第二个查询更新为指向右侧列(位置2)。查找有32个以上的密耳记录。位置1、位置2、位置3将在查找表的位置列中匹配。非常感谢。它与示例数据一起工作。如何处理这些海量数据的性能与基于集合的查询相比,游标基本上是慢的。但我从未尝试过批量更新游标。再次感谢。这里介绍的游标是为批量操作而设计的。这些是面向集合的语句,不是逐行的。非常感谢。它使用了示例数据。如何处理这些海量数据的性能与基于集合的查询相比,游标基本上是慢的。但我从未尝试过批量更新游标。再次感谢。这里介绍的游标是为批量操作而设计的。这些是面向集合的语句,不是逐行的。
    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;
    /