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

Trích xuất các hàng từ DB bao gồm các hàng cạn kiệt

Có thể có một số công cụ đã làm được điều đó, nhưng để tự ý trích xuất tất cả các bảng hàng từ bảng bắt đầu là một nhiệm vụ phát triển nhỏ. Tôi không thể viết toàn bộ cho bạn, nhưng tôi có thể giúp bạn bắt đầu - Tôi bắt đầu viết nó, nhưng sau khoảng 20 phút, tôi nhận ra rằng đó là một công việc nhiều hơn một chút mà tôi muốn cam kết trả lời không công.

Tôi có thể thấy nó được thực hiện tốt nhất bằng quy trình PL / SQL đệ quy sẽ sử dụng dbms_ouput và user_cons_columns &user_constraints để tạo câu lệnh chèn cho bảng nguồn. Bạn có thể gian lận một chút bằng cách viết tất cả các phần chèn như thể các cột là giá trị char, vì Oracle sẽ chuyển đổi ngầm bất kỳ giá trị char nào thành kiểu dữ liệu phù hợp, giả sử các tham số NLS của bạn giống hệt nhau trên hệ thống nguồn &đích.

Lưu ý, gói bên dưới sẽ có vấn đề nếu bạn có các mối quan hệ vòng tròn trong các bảng của mình; ngoài ra, trên các phiên bản trước của Oracle, bạn có thể hết dung lượng bộ đệm với dbms_output. Cả hai vấn đề đều có thể được giải quyết bằng cách chèn sql đã tạo vào bảng dàn có một chỉ mục duy nhất trên sql và hủy đệ quy nếu bạn nhận được một xung đột khóa duy nhất. Trình tiết kiệm thời gian lớn bên dưới là hàm MakeParamList, hàm này chuyển đổi con trỏ trả về danh sách các cột thành danh sách được phân tách bằng dấu phẩy hoặc một biểu thức duy nhất sẽ hiển thị giá trị của các cột đó trong biểu mẫu được trích dẫn, được phân tách bằng dấu phẩy khi chạy dưới dạng chọn mệnh đề trong một truy vấn đối với bảng.

Cũng lưu ý rằng gói sau sẽ không thực sự hoạt động cho đến khi bạn sửa đổi nó thêm (một trong những lý do tôi ngừng viết nó):Câu lệnh chèn ban đầu được tạo dựa trên giả định rằng đối số bind_vals được truyền vào sẽ dẫn đến một hàng duy nhất là được tạo ra - tất nhiên, điều này gần như chắc chắn không xảy ra khi bạn bắt đầu đệ quy (vì bạn sẽ có nhiều hàng con cho một hàng cha). Bạn sẽ cần thay đổi cách tạo câu lệnh đầu tiên (và các lệnh gọi đệ quy tiếp theo) để ở bên trong một vòng lặp để xử lý các trường hợp mà lệnh gọi đến lệnh gọi EXECUTE IMMEDIATE đầu tiên tạo ra nhiều hàng thay vì một hàng duy nhất. Những điều cơ bản để làm cho nó hoạt động ở đây, bạn chỉ cần nghiền nát các chi tiết và làm cho con trỏ bên ngoài hoạt động.

Một lưu ý cuối cùng cũng là:Không chắc bạn có thể chạy quy trình này để tạo một tập hợp các hàng, khi được chèn vào hệ thống đích, sẽ dẫn đến một tập dữ liệu "sạch", vì mặc dù bạn sẽ nhận được tất cả dữ liệu phụ thuộc, nhưng dữ liệu có thể phụ thuộc vào các bảng khác mà bạn không nhập (ví dụ:bảng con đầu tiên bạn gặp có thể có các khóa ngoại khác trỏ đến các bảng không liên quan đến bảng ban đầu của bạn). Trong trường hợp đó, bạn có thể muốn bắt đầu với các bảng chi tiết và làm việc theo cách của bạn lên thay vì xuống; làm điều đó, bạn cũng muốn đảo ngược thứ tự thành các câu lệnh bạn đã tạo, bằng cách sử dụng tiện ích tập lệnh hoặc bằng cách chèn sql vào bảng dàn như tôi đã đề cập ở trên, với một trình tự, sau đó chọn nó ra với sắp xếp giảm dần .

Đối với việc gọi nó, bạn chuyển danh sách các cột được phân tách bằng dấu phẩy để ràng buộc dưới dạng các ràng buộc_col và danh sách các giá trị được phân tách bằng dấu phẩy tương ứng dưới dạng các ràng buộc, ví dụ:

exec Data_extractor.MakeInserts ('MYTABLE', 'COL1, COL2', '99, 105')

Đây rồi:

CREATE OR REPLACE PACKAGE data_extractor
IS
   TYPE column_info IS RECORD(
      column_name   user_tab_columns.column_name%TYPE
   );

   TYPE column_info_cursor IS REF CURSOR
      RETURN column_info;

   FUNCTION makeparamlist(
      column_info   column_info_cursor
    , get_values    NUMBER
   )
      RETURN VARCHAR2;

   PROCEDURE makeinserts(
      source_table      VARCHAR2
    , constraint_cols   VARCHAR2
    , constraint_vals   VARCHAR2
   );
END data_extractor;


CREATE OR REPLACE PACKAGE BODY data_extractor
AS
   FUNCTION makeparamlist(
      column_info   column_info_cursor
    , get_values    NUMBER
   )
      RETURN VARCHAR2
   AS
   BEGIN
      DECLARE
         column_name   user_tab_columns.column_name%TYPE;
         tempsql       VARCHAR2(4000);
         separator     VARCHAR2(20);
      BEGIN
         IF get_values = 1
         THEN
            separator := ''''''''' || ';
         ELSE
            separator := '';
         END IF;

         LOOP
            FETCH column_info
             INTO column_name;

            EXIT WHEN column_info%NOTFOUND;
            tempsql := tempsql || separator || column_name;

            IF get_values = 1
            THEN
               separator := ' || '''''', '''''' || ';
            ELSE
               separator := ', ';
            END IF;
         END LOOP;

         IF get_values = 1
         THEN
            tempsql := tempsql || ' || ''''''''';
         END IF;

         RETURN tempsql;
      END;
   END;

   PROCEDURE makeinserts(
      source_table      VARCHAR2
    , constraint_cols   VARCHAR2
    , constraint_vals   VARCHAR2
   )
   AS
   BEGIN
      DECLARE
         basesql               VARCHAR2(4000);
         extractsql            VARCHAR2(4000);
         tempsql               VARCHAR2(4000);
         valuelist             VARCHAR2(4000);
         childconstraint_vals  VARCHAR2(4000);
      BEGIN
         SELECT makeparamlist(CURSOR(SELECT column_name
                                       FROM user_tab_columns
                                      WHERE table_name = source_table), 0)
           INTO tempsql
           FROM DUAL;

         basesql := 'INSERT INTO ' || source_table || '(' || tempsql || ') VALUES (';

         SELECT makeparamlist(CURSOR(SELECT column_name
                                       FROM user_tab_columns
                                      WHERE table_name = source_table), 1)
           INTO tempsql
           FROM DUAL;

         extractsql := 'SELECT ' || tempsql || ' FROM ' || source_table 
                       || ' WHERE (' || constraint_cols || ') = (SELECT ' 
                       || constraint_vals || ' FROM DUAL)';

         EXECUTE IMMEDIATE extractsql
                      INTO valuelist;

         -- This prints out the insert statement for the root row
         DBMS_OUTPUT.put_line(basesql || valuelist || ');');

         -- Now we construct the constraint_vals parameter for subsequent calls:
         SELECT makeparamlist(CURSOR(  SELECT column_name
                                         FROM user_cons_columns ucc
                                            , user_constraints uc
                                        WHERE uc.table_name = source_table
                                          AND ucc.constraint_name = uc.constraint_name
                                     ORDER BY position)
                             , 1)
           INTO tempsql
           FROM DUAL;

         extractsql := 'SELECT ' || tempsql || ' FROM ' || source_table 
                       || ' WHERE ' || constraint_cols || ' = ' || constraint_vals;

         EXECUTE IMMEDIATE extractsql
                      INTO childconstraint_vals;

         childconstraint_vals := childconstraint_vals;

-- Now iterate over the dependent tables for this table
-- Cursor on this statement:
--    SELECT uc.table_name child_table, uc.constraint_name fk_name
--      FROM user_constraints uc
--         , user_constraints ucp
--     WHERE ucp.table_name = source_table
--      AND uc.r_constraint_name = ucp.constraint_name;

         --   For each table in that statement, find the foreign key 
         --   columns that correspond to the rows
         --   in the parent table
         --  SELECT column_name
         --    FROM user_cons_columns
         --   WHERE constraint_name = fk_name
         --ORDER BY POSITION;

         -- Pass that columns into makeparamlist above to create 
         -- the constraint_cols argument of the call below:

         -- makeinserts(child_table, ChildConstraint_cols, childconstrain_vals);
      END;
   END;
END data_extractor;


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. ORA-00907 khi cố gắng tạo ràng buộc KIỂM TRA

  2. Sự cố khi gọi thủ tục được lưu trữ từ C # với CLOB lớn

  3. Sự khác biệt giữa mảng lồng nhau và mảng kết hợp là gì?

  4. Chọn tối đa (ngày) không hoạt động nếu các hàng có giá trị khác nhau, tôi chỉ muốn tìm nạp hàng có ngày cao nhất

  5. Ví dụ thu thập hàng loạt Oracle bằng cách sử dụng đối tượng loại Rowtype con trỏ