2012-04-23 51 views
0

我在阅读更多关于BULK COLLECT和dbms_sql的用法,并尝试将其应用于我的一个过程 在我的存储过程中,核心逻辑是从另一个值的INSERT到表中表作为BULK COLLECT和dbms_sql的用法

CREATE OR replace PROCEDURE My_procedure (pi_date  IN DATE, 
              po_error  OUT VARCHAR2, 
              po_error_desc OUT nocopy VARCHAR2) 
AS 
    curr_date DATE; 
BEGIN 
    CURR_DATE := PI_DATE; 

    INSERT INTO t1 
       (col1, 
       col2, 
       col3, 
       col4, 
       col5) 
    SELECT t2.col1, 
      t2.col2, 
      t2.col3, 
      t2.col4, 
      CURR_DATE 
EXCEPTION 
    WHEN OTHERS THEN 
      PO_ERROR := -1; 

      PO_ERROR_DESC := 'proc nam : ' 
           || 'my_procedure' 
           || ', err_num :' 
           || SQLCODE 
           || ' | , err_msg :' 
           || SQLERRM; 

      ROLLBACK; 

      DBMS_SESSION.free_unused_user_memory; 
END; 

但是因为这将被插入到另一个表中的数据是巨大的,在我的第二次修改程序

我已经使用BULK收集和DBMS_SQL如下

CREATE OR replace PROCEDURE My_procedure (pi_date  DATE, 
              po_error  OUT VARCHAR2, 
              po_error_desc OUT nocopy VARCHAR2) 
AS 
    v_curr_date DATE; 
    l_col1      dbms_sql.Varchar2_Table; 
    l_col2      dbms_sql.Varchar2_Table; 
    l_col3      dbms_sql.Number_Table; 
    l_col4      dbms_sql.Number_Table; 

    CURSOR c1 IS 
    SELECT * 
    FROM t2; 

BEGIN 
    V_CURR_DATE := PI_DATE; 

    PO_ERROR := 0; 

    OPEN c1; 

    LOOP 
     FETCH c1 bulk collect INTO l_col1, l_col2, l_col3, l_col4 limit 1000; 

     forall indx IN 1..l_col1.COUNT 
      INSERT INTO t2 
         (col1, 
         col2, 
         col3, 
         col4, 
         col5) 
      VALUES  (L_col1(indx), 
         L_col2(indx), 
         L_col3(indx), 
         L_col4(indx), 
         V_CURR_DATE); 

EXCEPTION 
    WHEN OTHERS THEN 
      PO_ERROR := -1; 

      PO_ERROR_DESC := 'proc nam : ' 
           || 'my_procedure' 
           || ', err_num :' 
           || SQLCODE 
           || ' | , err_msg :' 
           || SQLERRM; 

      ROLLBACK; 

      DBMS_SESSION.free_unused_user_memory; 
END; 

因此,这里是我的第二个例子中,我已经使用BULK收集按照文档但是

有人能poinpoint的dbms_sql.Varchar2_Table确切的使用情况如何?

如以上那样,如果COL1的实际长度是VARCHAR2(40),但dbms_sql.Varchar2_Table使用VARCHAR2(2000)

TYPE varchar2_table IS TABLE OF VARCHAR2(2000) INDEX BY BINARY_INTEGER; 
+0

你确切的问题是什么?您提供的代码充斥着语法错误。你应该提供你正在使用的确切源代码,并提到你遇到的问题是什么 – Sathya 2012-04-23 09:51:38

+0

我的问题是我在第二个例子中使用BULK COLLECT和使用dbms_sql做另一个表的INSERT的方法是正确与否。希望这很好。 – ronan 2012-04-23 12:10:06

回答

0

您的批量收集循环需要作为使用的是LIMIT子句是一个完整的环:

-- Open the cursor 
OPEN cursor_name; 
-- Loop through cursor records 
LOOP 

    -- Fetch the cursor results into a collection limited to a set figure 
    FETCH cursor_name BULK COLLECT INTO table 
    LIMIT 1000; 

    -- For every record in the collection 
    FORALL x IN INDICES OF table 
     INSERT INTO target_table 
     (col) 
     VALUES 
     table(x); 

    -- Set up the limit loop exit criteria 
    EXIT WHEN table.COUNT < 1000; -- Less that the limit you set  
-- End the loop 
END LOOP; 
-- Close the cursor 
CLOSE cursor_name; 

这个伪码片段应该让你开始正确的路径让你的批量代码工作。您当前的DBMS_SQL表的声明看起来很好。

希望它有帮助...

+0

谢谢我关于dbms_sql的问题如上所示,如果col1的实际长度为VARCHAR2(40),但dbms_sql.Varchar2_Table使用VARCHAR2(2000)并按照oracle文档varchar2_table是TYPE varchar2_table IS TABLE OF VARCHAR2(2000)INDEX BY BINARY_INTEGER;那么为什么当实际长度是40时使用2000空间? – ronan 2012-04-23 13:12:05

+0

这是一个方便的构造函数,用于快速高效地使用包含'VARCHAR2'值的表。如果您真的担心VARCHAR2(2000)数组正在使用额外的字节,那么创建您自己的集合以使用最大长度为40的类型。TYPE array_40_chartype IS TABLE VARCHAR2(40)INDEX BY BINARY_INTEGER;'Then declare一个使用类型的表:'array_40_char array_40_chartype;'瞧。 – Ollie 2012-04-23 13:25:35

+0

感谢Ollie在你的例子中FETCH cursor_name BULK COLLECT INTO表,这里的表是一种集合权? – ronan 2012-04-24 03:21:34