简体   繁体   中英

How to write procedure to copy data from one table to another table

Hello I have this situation

I have a table with 400 millions of records I want to migrate some data to another table for get better performance.

I know that the process could be slow and heavy and I want to execute something like this

INSERT INTO TABLLE_2  SELECT NAME,TAX_ID,PROD_CODE FROM TABLE_1;

But I want this in a procedure that iterates the table from 50000 to 50000 records.

I saw this but it DELETE the rows and the target is SQLServer and not Oracle

WHILE 1 = 1
BEGIN
  DELETE TOP (50000) FROM DBO.VENTAS 
    OUTPUT
      Deleted.AccountNumber,
      Deleted.BillToAddressID,  
      Deleted.CustomerID,
      Deleted.OrderDate,
      Deleted.SalesOrderNumber,
      Deleted.TotalDue    
    
      INTO DATOS_HISTORY.dbo.VENTAS 
      WHERE OrderDate >= '20130101' 
      and OrderDate < '20140101'

  IF @@ROWCOUNT = 0 BREAK;
END;

If it's just for a one-time migration, don't paginate/iterate at all. Just use a pdml append insert-select:

BEGIN
  EXECUTE IMMEDIATE 'alter session enable parallel dml';

  INSERT /*+ parallel(8) nologging append */ INTO table_2 
  SELECT name,tax_id,prod_code from table_1;

  COMMIT;
  EXECUTE IMMEDIATE 'alter session disable parallel dml';
END;

Or if the table doesn't yet exist, CTAS it to be even simpler:

CREATE OR REPLACE TABLE table_2 PARALLEL (DEGREE 8) NOLOGGING AS 
SELECT name,tax_id,prod_code FROM table_1;

If you absolutely must iterate due to other business needs you didn't mention, you can use PL/SQL for that as well:

DECLARE
  CURSOR cur_test
  IS
  SELECT name,tax_id,prod_code
    FROM table_1;

  TYPE test_tabtype IS TABLE OF cur_test%ROWTYPE; 
  tab_test test_tabtype;
  var_limit integer := 50000;
BEGIN
  OPEN cur_test;
  FETCH cur_test BULK COLLECT INTO tab_test LIMIT var_limit;

  LOOP
    -- do whatever else you need to do

    FORALL i IN tab_test.FIRST .. tab_test.LAST
    INSERT INTO table_2 
           (name,tax_id,prod_code)
    VALUES (tab_test(i).name, tab_test(i).tax_id, tab_test(i).prod_code);

    COMMIT;

    EXIT WHEN tab_test.COUNT < var_limit;
    FETCH cur_test BULK COLLECT INTO tab_test LIMIT var_limit;
  END LOOP;

  CLOSE cur_test;
END;

That won't be nearly as fast, though. If you need even faster, you can create a SQL object and nested table type instead of the PL/SQL types you see here and then you can do a normal INSERT /*+ APPEND */ SELECT... statement that will use direct path. But honestly, I doubt you really need iteration at all..

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM