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

Hiểu sự khác biệt giữa Bảng và API Giao dịch

Hãy bắt đầu với API Bảng. Đây là hoạt động dàn xếp quyền truy cập vào các bảng thông qua API PL / SQL. Vì vậy, chúng tôi có một gói cho mỗi bảng, gói này sẽ được tạo từ từ điển dữ liệu. Gói này trình bày một bộ thủ tục tiêu chuẩn để phát hành DML dựa trên bảng và một số hàm để truy xuất dữ liệu.

Bằng cách so sánh, API giao dịch đại diện cho Đơn vị công việc. Nó hoàn toàn không tiết lộ bất kỳ thông tin nào về các đối tượng cơ sở dữ liệu bên dưới. API giao dịch cung cấp khả năng đóng gói tốt hơn và giao diện gọn gàng hơn.

Sự tương phản là như thế này. Hãy xem xét các quy tắc kinh doanh này để tạo Phòng mới:

  1. Bộ phận mới phải có Tên và Vị trí
  2. Bộ phận mới phải có một người quản lý, người này phải là một Nhân viên hiện có
  3. Các nhân viên hiện tại khác có thể được chuyển đến Bộ phận mới
  4. Nhân viên mới có thể được chỉ định vào Bộ phận mới
  5. Bộ phận mới phải có ít nhất hai Nhân viên được chỉ định (bao gồm cả người quản lý)

Sử dụng API Bảng, giao dịch có thể trông giống như sau:

DECLARE
    dno pls_integer;
    emp_count pls_integer;
BEGIN
    dept_utils.insert_one_rec(:new_name, :new_loc, dno);
    emp_utils.update_one_rec(:new_mgr_no ,p_job=>'MGR’ ,p_deptno=>dno);
    emp_utils.update_multi_recs(:transfer_emp_array, p_deptno=>dno);
    FOR idx IN :new_hires_array.FIRST..:new_hires_array.LAST LOOP
        :new_hires_array(idx).deptno := dno;
    END LOOP;
    emp_utils.insert_multi_recs(:new_hires_array);
    emp_count := emp_utils.get_count(p_deptno=>dno); 
    IF emp_count < 2 THEN
        raise_application_error(-20000, ‘Not enough employees’);
    END IF;
END;
/

Trong khi với API giao dịch thì đơn giản hơn nhiều:

DECLARE
    dno subtype_pkg.deptno;
BEGIN
    dept_txns.create_new_dept(:new_name
                                , :new_loc
                                , :new_mgr_no
                                , :transfer_emps_array
                                , :new_hires_array
                                , dno);
END;
/

Vậy tại sao lại có sự khác biệt trong việc truy xuất dữ liệu? Bởi vì phương pháp API giao dịch không khuyến khích get() chung chung các hàm để tránh việc sử dụng vô tâm các câu lệnh SELECT kém hiệu quả.

Ví dụ:nếu bạn chỉ muốn mức lương và hoa hồng cho một Nhân viên, hãy truy vấn điều này ...

select sal, comm
into l_sal, l_comm
from emp
where empno = p_eno;

... tốt hơn là thực hiện điều này ...

l_emprec := emp_utils.get_whole_row(p_eno);

... đặc biệt nếu bản ghi Nhân viên có các cột LOB.

Nó cũng hiệu quả hơn:

l_sal := emp_utils.get_sal(p_eno);
l_comm := emp_utils.get_comm(p_eno);

... nếu mỗi getters đó thực thi một câu lệnh SELECT riêng biệt. Không phải là không biết:đó là một thực hành OO tồi dẫn đến hiệu suất cơ sở dữ liệu tồi tệ.

Những người đề xuất API bảng lập luận cho chúng trên cơ sở rằng chúng bảo vệ nhà phát triển không cần phải suy nghĩ về SQL. Những người không dùng họ không thích API Bảng vì lý do tương tự . Ngay cả các API Bảng tốt nhất cũng có xu hướng khuyến khích xử lý RBAR. Nếu chúng ta viết SQL của riêng mình mỗi lần, chúng ta có nhiều khả năng chọn cách tiếp cận dựa trên tập hợp.

Sử dụng AP giao dịch không nhất thiết loại trừ việc sử dụng get_resultset() chức năng. Vẫn còn rất nhiều giá trị trong một API truy vấn. Nhưng nó có nhiều khả năng được xây dựng từ các dạng xem và chức năng triển khai các phép nối hơn là CHỌN trên các bảng riêng lẻ.

Ngẫu nhiên, tôi nghĩ rằng việc xây dựng các API giao dịch trên các API bảng không phải là một ý tưởng hay:chúng ta vẫn có các câu lệnh SQL được viết sẵn thay vì các phép nối được viết cẩn thận.

Như một minh họa, đây là hai cách triển khai khác nhau của API giao dịch để cập nhật mức lương của mọi Nhân viên trong một Khu vực (Khu vực là một bộ phận quy mô lớn của tổ chức; Các phòng ban được phân công cho các Khu vực).

Phiên bản đầu tiên không có SQL thuần mà chỉ có các lệnh gọi Table API, tôi không nghĩ đây là một người đàn ông rơm:nó sử dụng loại chức năng mà tôi đã thấy trong các gói Table API (mặc dù một số sử dụng SQL động chứ không phải là các thủ tục SET_XXX () có tên) .

create or replace procedure adjust_sal_by_region
    (p_region in dept.region%type
           , p_sal_adjustment in number )
as
    emps_rc sys_refcursor;
    emp_rec emp%rowtype;
    depts_rc sys_refcursor;
    dept_rec dept%rowtype;
begin
    depts_rc := dept_utils.get_depts_by_region(p_region);

    << depts >>
    loop
        fetch depts_rc into dept_rec;
        exit when depts_rc%notfound;
        emps_rc := emp_utils.get_emps_by_dept(dept_rec.deptno);

        << emps >>
        loop
            fetch emps_rc into emp_rec;
            exit when emps_rc%notfound;
            emp_rec.sal := emp_rec.sal * p_sal_adjustment;
            emp_utils.set_sal(emp_rec.empno, emp_rec.sal);
        end loop emps;

    end loop depts;

end adjust_sal_by_region;
/

Cách triển khai tương đương trong SQL:

create or replace procedure adjust_sal_by_region
    (p_region in dept.region%type
           , p_sal_adjustment in number )
as
begin
    update emp e
    set e.sal = e.sal * p_sal_adjustment
    where e.deptno in ( select d.deptno 
                        from dept d
                        where d.region = p_region );
end adjust_sal_by_region;
/

Điều này đẹp hơn nhiều so với các vòng lặp con trỏ lồng nhau và cập nhật hàng đơn của phiên bản trước. Điều này là do trong SQL, rất khó để viết phép nối, chúng ta cần chọn Nhân viên theo Vùng. Việc sử dụng Table API sẽ khó hơn rất nhiều vì Vùng không phải là khóa của Nhân viên.

Công bằng mà nói, nếu chúng ta có Table API hỗ trợ SQL động, mọi thứ tốt hơn nhưng vẫn không lý tưởng:

create or replace procedure adjust_sal_by_region
    (p_region in dept.region%type
           , p_sal_adjustment in number )
as
    emps_rc sys_refcursor;
    emp_rec emp%rowtype;
begin
    emps_rc := emp_utils.get_all_emps(
                    p_where_clause=>'deptno in ( select d.deptno 
                        from dept d where d.region = '||p_region||' )' );

    << emps >>
    loop
        fetch emps_rc into emp_rec;
        exit when emps_rc%notfound;
        emp_rec.sal := emp_rec.sal * p_sal_adjustment;
        emp_utils.set_sal(emp_rec.empno, emp_rec.sal);
    end loop emps;

end adjust_sal_by_region;
/

từ cuối cùng

Đã nói tất cả những điều đó, có những tình huống mà API Bảng có thể hữu ích, những tình huống khi chúng ta chỉ muốn tương tác với các bảng đơn lẻ theo những cách khá chuẩn. Một trường hợp rõ ràng có thể là sản xuất hoặc tiêu thụ nguồn cấp dữ liệu từ các hệ thống khác, ví dụ:ETL.

Nếu bạn muốn điều tra việc sử dụng Table API, nơi tốt nhất để bắt đầu là Tiện ích CodeGen Quest của Steven Feuerstein (trước đây là QNXO). Điều này cũng tốt như các máy phát điện TAPI nhận được và hoàn toàn miễn phí.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách thiết lập Thư mục đích đến của bản ghi lưu trữ trong cơ sở dữ liệu Oracle

  2. java.lang.UnsatisfiedLinkError:không có ocijdbc11 trong java. library.path

  3. Chuyển đổi ngày chuỗi ISO-8601 thành kiểu dữ liệu dấu thời gian của oracle

  4. Làm cách nào để bạn thực thi SQL từ bên trong một tập lệnh bash?

  5. oracle - Chia nhiều giá trị được phân tách bằng dấu phẩy trong bảng oracle thành nhiều hàng