Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Làm cách nào để hợp nhất hai lược đồ-cơ sở dữ liệu tương tự trong PL / SQL?

Như đã hứa sẽ trợ giúp trong nhận xét của tôi, tôi đã chuẩn bị một mã động mà bạn có thể thử lấy dữ liệu merged với bảng nguồn và bảng đích. Logic như sau:

Bước 1:Lấy tất cả các tên bảng từ SOURCE lược đồ. Trong truy vấn bên dưới, bạn có thể cần thay thế tên lược đồ (chủ sở hữu) tương ứng. Với mục đích thử nghiệm, tôi chỉ lấy 1 bảng nên khi bạn chạy nó, hãy xóa mệnh đề lọc tên bảng.

Bước 2:Lấy tên cột bị ràng buộc cho bảng. Điều này được sử dụng để chuẩn bị ON mệnh đề sau này sẽ được sử dụng cho MERGE tuyên bố.

Bước 3:Lấy tên cột không bị ràng buộc cho bảng. Điều này sẽ được sử dụng trong UPDATE mệnh đề khi sử dụng MERGE .

Bước 4:Chuẩn bị insert liệt kê khi dữ liệu không khớp với ON điều kiện của MERGE bản tường trình.

Đọc các nhận xét nội dòng của tôi để hiểu từng bước.

CREATE OR REPLACE PROCEDURE COPY_TABLE
AS
Type OBJ_NME is table of varchar2(100) index by pls_integer;

--To hold Table name
v_obj_nm OBJ_NME ;

--To hold Columns of table
v_col_nm OBJ_NME;

v_othr_col_nm OBJ_NME;
on_clause VARCHAR2(2000);
upd_clause VARCHAR2(4000);
cntr number:=0;
v_sql VARCHAR2(4000);

col_list1  VARCHAR2(4000);
col_list2  VARCHAR2(4000);
col_list3  VARCHAR2(4000);
col_list4  varchar2(4000);
col_list5  VARCHAR2(4000);
col_list6  VARCHAR2(4000);
col_list7  VARCHAR2(4000);
col_list8  varchar2(4000);

BEGIN

--Get Source table names
SELECT OBJECT_NAME
BULK COLLECT INTO v_obj_nm
FROM all_objects 
WHERE owner LIKE  'RU%' -- Replace `RU%` with your Source schema name here
AND object_type = 'TABLE'
and object_name ='TEST'; --remove this condition if you want this to run for all tables

FOR I IN 1..v_obj_nm.count
loop
--Columns with Constraints 
  SELECT column_name
  bulk collect into v_col_nm 
  FROM user_cons_columns
  WHERE table_name = v_obj_nm(i);  

--Columns without Constraints remain columns of table
SELECT *
BULK COLLECT INTO v_othr_col_nm
from (
      SELECT column_name 
      FROM user_tab_cols
      WHERE table_name = v_obj_nm(i)
      MINUS
      SELECT column_name  
      FROM user_cons_columns
      WHERE table_name = v_obj_nm(i));

--Prepare Update Clause  
 FOR l IN 1..v_othr_col_nm.count
  loop
   cntr:=cntr+1;
   upd_clause := 't1.'||v_othr_col_nm(l)||' = t2.' ||v_othr_col_nm(l);    
   upd_clause:=upd_clause ||' and ' ;

   col_list1:= 't1.'||v_othr_col_nm(l) ||',';
   col_list2:= col_list2||col_list1;   

   col_list5:= 't2.'||v_othr_col_nm(l) ||',';
   col_list6:= col_list6||col_list5;

   IF (cntr = v_othr_col_nm.count)
   THEN 
    --dbms_output.put_line('YES');
     upd_clause:=rtrim(upd_clause,' and');
     col_list2:=rtrim( col_list2,',');
     col_list6:=rtrim( col_list6,',');
   END IF;
     dbms_output.put_line(col_list2||col_list6); 
   --dbms_output.put_line(upd_clause);
   End loop;
  --Update caluse ends     

   cntr:=0; --Counter reset  

 --Prepare ON clause  
  FOR k IN 1..v_col_nm.count
  loop
   cntr:=cntr+1;
   --dbms_output.put_line(v_col_nm.count || cntr);
   on_clause := 't1.'||v_col_nm(k)||' = t2.' ||v_col_nm(k);    
   on_clause:=on_clause ||' and ' ;

   col_list3:= 't1.'||v_col_nm(k) ||',';
   col_list4:= col_list4||col_list3;    

   col_list7:= 't2.'||v_col_nm(k) ||',';
   col_list8:= col_list8||col_list7;    

   IF (cntr = v_col_nm.count)
   THEN 
    --dbms_output.put_line('YES');
    on_clause:=rtrim(on_clause,' and');
    col_list4:=rtrim( col_list4,',');
    col_list8:=rtrim( col_list8,',');
   end if;

   dbms_output.put_line(col_list4||col_list8);
 -- ON clause ends

 --Prepare merge Statement

    v_sql:= 'MERGE INTO '|| v_obj_nm(i)||' t1--put target schema name before v_obj_nm
              USING (SELECT * FROM '|| v_obj_nm(i)||') t2-- put source schema name befire v_obj_nm here 
              ON ('||on_clause||')
              WHEN MATCHED THEN
              UPDATE
              SET '||upd_clause ||              
              ' WHEN NOT MATCHED THEN
              INSERT  
              ('||col_list2||','
                ||col_list4||
              ')
              VALUES
              ('||col_list6||','
                ||col_list8||          
               ')';

      dbms_output.put_line(v_sql);   
      execute immediate v_sql;
  end loop;    
End loop;
END;
/

Thực hiện:

exec COPY_TABLE

Đầu ra:

anonymous block completed

Tái bút:Tôi đã kiểm tra điều này với một bảng có 2 cột trong đó tôi có ràng buộc khóa duy nhất. DDL của bảng như sau:

Cuối cùng, tôi ước bạn có thể hiểu mã của tôi (bạn là một noob) và thực hiện một cái gì đó tương tự nếu phần trên không đáp ứng được yêu cầu của bạn.

 CREATE TABLE TEST
       (    COL2 NUMBER, 
            COLUMN1 VARCHAR2(20 BYTE), 
            CONSTRAINT TEST_UK1 UNIQUE (COLUMN1)  
       ) ;


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. chọn từ một bảng, chèn vào một bảng khác truy vấn sql oracle

  2. ORA-04091:bảng xx_xx đang đột biến, trình kích hoạt / chức năng có thể không nhìn thấy nó

  3. giữ một kết nối với DB hoặc đóng mở theo nhu cầu

  4. Cách làm mới chế độ xem cụ thể hóa trong oracle

  5. Kiểm tra định dạng DATE trong Oracle