如何从选择查询

时间:2015-04-22 10:33:54

标签: sql perl plsql sqlplus

嗨朋友我有一个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& amp; amp;因为这个服务器是第三方服务器所以我不能在这个

上做任何chnages

更新:1

我试过以下两个程序&运行特定日期,表有600万条记录。但查询一直在运行&即使在2天后也没有产生任何产量...

程序#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;

程序#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 个答案:

答案 0 :(得分: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:如果你对我所说的一无所知,请先查看这些链接。

相关问题