首页 文章

如何从select查询中为PL / SQL循环提供值

提问于
浏览
0

嗨朋友,我有一个perl脚本,通过sqlplus与oracle Db交互 . 我在这里运行两个查询 . 第一个查询从视图中提取特定日期的序列号并写入文件 .

SELECT DISTINCT serialnumber FROM VOUCHERHISTORYCLIENTV WHERE at LIKE '&1';    (where &1 = $date)

然后perl循环读取此文件,逐行获取序列号并运行以下查询,将数据写入另一个文件,然后由以下perl代码处理 . 现在这些序列号太大了,所以循环连接到sqlplus的每次迭代运行查询并生成输出然后断开连接 . 这就是为什么它需要花费太多时间 .

SELECT * FROM VSOWNERUPE07.VOUCHERHISTORYCLIENTV WHERE serialnumber = '&1';    (where &1 = $serialnumber)

有什么方法我不需要再次连接和断开sqlplus会话吗?我最终想要的是对unix文件中附加的每个迭代的第二个查询的结果 . 所以我的perl脚本可以格式化它们 . 我猜pl / sql循环可以做到这一点......但我从来没有在pl / sql上工作过...你能帮我吗?

PS:我不能在这里使用DBD :: oracle因为我在solaris mahine上安装这个模块时面临太多问题而且这个服务器是第三方服务器所以我不能在这个上做任何chnages

Update: 1

我尝试了以下两个程序并运行特定日期,其中表有600万条记录 . 但查询一直在运行,即使在2天后也没有产生任何输出......

Procedure# 1:

DECLARE

    CURSOR CUR1 IS
    SELECT DISTINCT serialnumber FROM VSOWNERUPE07.VOUCHERHISTORYCLIENTV WHERE at LIKE '&1';

    CURSOR CUR2(p_ser_num NUMBER) IS
    SELECT serialnumber, state, at as time1, operatorid  FROM VSOWNERUPE07.VOUCHERHISTORYCLIENTV WHERE serialnumber = p_ser_num;

    BEGIN

    FOR l_cur1 IN CUR1
    LOOP
      NULL;
      FOR l_cur2 IN CUR2(l_cur1.serialnumber)
      LOOP

       DBMS_OUTPUT.PUT_LINE(l_cur2.serialnumber||' '||l_cur2.state ||' '||l_cur2.time1 ||' '||l_cur2.operatorid );

      END LOOP;
    END LOOP;
    END;

    /

    quit;

Procedure# 2:

DECLARE

CURSOR CUR1 IS
SELECT DISTINCT serialnumber FROM VSOWNERUPE07.VOUCHERHISTORYCLIENTV WHERE at LIKE '&1';

TYPE t_tab1 IS TABLE OF CUR1%ROWTYPE;

l_tab1 t_tab1;

CURSOR CUR2(p_ser_num NUMBER) IS
SELECT serialnumber, state, at as time1, operatorid  FROM VSOWNERUPE07.VOUCHERHISTORYCLIENTV WHERE serialnumber = p_ser_num;

TYPE t_tab2 IS TABLE OF CUR2%ROWTYPE;

l_tab2 t_tab2;


BEGIN

  OPEN CUR1;
  LOOP
   FETCH CUR1 BULK COLLECT INTO l_tab1;
   EXIT WHEN CUR1%NOTFOUND;
  END LOOP;
  CLOSE CUR1;
 FOR i in 1..l_tab1.COUNT
   LOOP
    OPEN CUR2(l_tab1(i).serialnumber);
       LOOP
          FETCH CUR2 BULK COLLECT INTO l_tab2;
          EXIT WHEN CUR2%NOTFOUND;
       END LOOP;
    CLOSE CUR2;
       for j in 1..l_tab2.COUNT
            LOOP
              DBMS_OUTPUT.PUT_LINE(l_tab2(j).serialnumber||' '||l_tab2(j).state ||' '||l_tab2(j).time1 ||' '||l_tab2(j).operatorid );
            END LOOP;
   END LOOP;

END;

/

quit;

我可以改进上述程序,还是有其他方法可以帮助我们完成这项工作?请帮忙 .

1 回答

  • 2

    一次,您可以使用此单个查询替换2个查询:

    SELECT * FROM VSOWNERUPE07.VOUCHERHISTORYCLIENTV 
       WHERE serialnumber IN (SELECT DISTINCT serialnumber FROM  
                               VOUCHERHISTORYCLIENTV WHERE at LIKE '&1');
    

    并将输出写入最终文件 .

    你看到这个有什么问题吗?

    UPDATE1

    首先,将它分解为2个不同的查询几乎从来都不是一个更好的解决方案.SQL上下文切换会杀了你 .

    分别在两个表的 serialnumberat 列上构建索引,并尝试使用单个查询 .
    如果即便如此,你也可以试试UPDATE2 .

    UPDATE2

    如果问题太多,则使用批量处理 . 这个过程有点乏味,但旨在处理这种情况 .

    有关如何进行批量处理的一些示例是hereherehere .

    为此,您可能需要编写PLSQL过程 .
    在该过程中,将所有数据批量收集到第一个查询中的varray中 . 现在使用此varray运行第二个选择查询并收集您的数据 .

    下一个
    您可以将这些序列号放入,比如说另一个v阵列并将其写入文件
    要么
    创建一个新的单列表并将其写入此新表 . 然后将它写入文件/从perl分别查询这个新表 .

    注意1:如果您使用单独的表,请在每次运行后截断它;并在其上构建索引
    注2:如果你对我所说的一无所知,请先查看这些链接 .

相关问题