0

BULK COLLECT と dbms_sql の使用法について詳しく読んでいて、プロシージャの 1 つに同じことを適用しようとしました。ストアド プロシージャのコア ロジックは、別のテーブルの値からテーブルへの INSERT です。

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;

ただし、別のテーブルに挿入されるデータは巨大であるため、2 番目の変更手順では

以下のように 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; 

これが私の2番目の例です。ドキュメントに従ってBULK collectを使用しましたが、

誰かが正確な使用法を指摘できますかdbms_sql.Varchar2_Table?

上記のように、col1 の実際の長さは VARCHAR2(40) ですがdbms_sql.Varchar2_TableVARCHAR2(2000)

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

1 に答える 1

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テーブルの現在の宣言は問題ないようです。

それが役に立てば幸い...

于 2012-04-23T12:21:35.637 に答える