一个语句中有多个游标

时间:2014-01-13 19:51:00

标签: sql oracle oracle11g cursor oracle-spatial

我必须处理三个具有几何形状的表。

DECLARE
  CURSOR c1 IS
    SELECT
      store_number,
      0 AS total_area,
      0 AS bg_id,
      0 AS store_geom
    FROM table1 WHERE client_id = 1 AND org_id = 1;

  TYPE c1_tab_type IS TABLE OF c1%ROWTYPE;
  c1_list c1_tab_type;

BEGIN

  FOR r1 IN c1
  LOOP

    SELECT bg_id, store_number, total_area
    BULK COLLECT INTO c1_list
    FROM (
        SELECT
          bg_id,
          store_number,
          b.geometry                                                       store_geom,
          ((sdo_geom.SDO_AREA(sdo_geom.SDO_INTERSECTION(a.geometry, b.geometry, 0.005), 0.005, 'unit=sq_mile') /
            sdo_geom.SDO_AREA((a.geometry), 0.005, 'unit=sq_mile')) * 100) total_area
        FROM table2 a, table1 b
        WHERE store_number != r1.store_number
              AND sdo_relate(a.geometry, b.geometry, 'mask=anyinteract') = 'TRUE');

    IF total_area = 100 THEN
      FOR i IN 1..c1_list.count LOOP
        INSERT INTO temp_prop_area_100 VALUES c1_list(i);
      END LOOP;
    ELSE IF
      FOR i IN 1..c1_list.count LOOP
        INSERT INTO temp_Prop_area_block VALUES c1_list(i);
      END LOOP;
    END IF;

  END LOOP;
END;

因此,我从表1中选择一条记录(所有三个表中最大的几何图形),并覆盖表2中较小的多边形。我从表2中得到重叠几何图形的列表。这可能有一些相交并且其中一些完全位于表1的多边形之下。

然后我想把它们放到两个不同的表中。完全在temp_prop_area中的那些以及在temp_prop_area_block中相交的那些。

现在我遇到的问题是,当我得到所有交叉多边形的id(temp_prop_area_block)时,我希望将这个多边形覆盖在表3中多边形区域的多边形上。这些多边形区域也是如此。交叉和交叉区域是什么。

多边形大小按此顺序排列,表1中的多边形为最大,表2或temp_prop_area_block为多边形,然后是表3中的多边形。

1 个答案:

答案 0 :(得分:2)

你有几个选择。在您定义的记录类型之外,total_area不存在,因此您无法在显示的if中使用它,但您可以稍微调整一下:

...
                  For i in 1..c1_list.count loop
                       if c1_list(i).total_area=100
                          then                   
                            insert into temp_Prop_area_100
                            values c1_list(i);
                       else
                            insert into temp_Prop_area_block
                            values c1_list(i);
                       end if;
                  End Loop;
            End Loop;
End;

或者您可以将列表拆分为两个:

   Type C1_TAB_TYPE is table of c1%ROWTYPE;      
   c1_list c1_TAB_TYPE;
   c1_list_100 c1_TAB_TYPE;
   c1_list_block c1_TAB_TYPE;
...
                  For i in 1..c1_list.count loop
                       if c1_list(i).total_area=100
                          then                   
                            c1_list_100.extend();
                            c1_list_100(c1_list_100.last) := c1_list(i);
                       else
                            c1_list_block.extend();
                            c1_list_block(c1_list_block.last) := c1_list(i);
                       end if;
                  End Loop;

                  For i in 1..c1_list_100.count loop
                       insert into temp_Prop_area_100
                       values c1_list_100(i);
                  End Loop;
                  For i in 1..c1_list_block.count loop
                       insert into temp_Prop_area_block
                       values c1_list_block(i);
                  End Loop;
            End Loop;
End;

看起来它增加了额外的复杂性而没有太大的收益,如果你继续使用单独的插入,这可能是正确的。但是,这也允许您使用a previous answer中提到的forall语法:

    Type C1_TAB_TYPE is table of temp_prop_area%ROWTYPE;      
...
                  Forall i in 1..c1_list_100.count
                       insert into temp_Prop_area_100
                       values c1_list_100(i);
                  Forall i in 1..c1_list_block.count
                       insert into temp_Prop_area_block
                       values c1_list_block(i);
            End Loop;
End;

您还可以使用不同的过滤器对两个列表中的单独select ... bulk collect语句执行操作,但这会导致对表进行两次操作,效率可能会降低。