2012-04-23 3 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 COLLECT и 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

+0

. Мой вопрос - это подход, который я использовал в примере второй использования BULK COLLECT и использование dbms_sql для ввода INSERT в другую таблицу. правильно или нет. Надеюсь, все в порядке. – ronan

ответ

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 is Как показано выше, если фактическая длина col1 равна VARCHAR2 (40), но dbms_sql.Varchar2_Table использует VARCHAR2 (2000) и в соответствии с документацией оракула varchar2_table - TYPE varchar2_table IS ТАБЛИЦА VARCHAR2 (2000) INDEX BY BINARY_INTEGER; так зачем использовать пространство 2000, когда фактическая длина равна 40? – ronan

+0

Это удобный конструктор для быстрого и эффективного использования таблицы, содержащей значения VARCHAR2. Если вы действительно беспокоитесь о том, что дополнительные байты используются массивом VARCHAR2 (2000), тогда создайте свою собственную коллекцию для использования с максимальной длиной 40. 'TYPE array_40_chartype IS ТАБЛИЦА VARCHAR2 (40) INDEX BY BINARY_INTEGER;' Затем объявите таблицу с использованием типа: 'array_40_char array_40_chartype;' voila. – Ollie

+0

Спасибо Ollie в вашем примере FETCH cursor_name BULK COLLECT INTO table, вот таблица является типом коллекции справа? – ronan

Смежные вопросы