Vì bạn đang sử dụng Oracle, tôi sẽ tạo các hàm Pipelined TABLE. Hàm lấy tham số và trả về một đối tượng (mà bạn phải tạo) và sau đó bạn SELECT * hoặc thậm chí các cột cụ thể từ nó bằng hàm TABLE() và có thể sử dụng nó với mệnh đề WHERE hoặc JOIN. Nếu bạn muốn một đơn vị tái sử dụng (một hàm) bạn không bị giới hạn chỉ trả về các giá trị (tức là một hàm vô hướng), bạn có thể viết một hàm trả về các hàng hoặc các tập bản ghi. một cái gì đó như thế này:
FUNCTION RETURN_MY_ROWS(Param1 IN type...ParamX IN Type)
RETURN PARENT_OBJECT PIPELINED
IS
local_curs cursor_alias; --you need a cursor alias if this function is in a Package
out_rec ROW_RECORD_OF_CUSTOM_OBJECT:=ROW_RECORD_OF_CUSTOM_OBJECT(NULL, NULL,NULL) --one NULL for each field in the record sub-object
BEGIN
OPEN local_curs FOR
--the SELECT query that you're trying to encapsulate goes here
-- and it can be very detailed/complex and even have WITH() etc..
SELECT * FROM baseTable WHERE col1 = x;
-- now that you have captured the SELECT into a Cursor
-- here you put a LOOP to take what's in the cursor and put it in the
-- child object (that holds the individual records)
LOOP
FETCH local_curs --opening the ref-cursor
INTO out_rec.COL1,
out_rec.COL2,
out_rec.COL3;
EXIT WHEN local_curs%NOTFOUND;
PIPE ROW(out_rec); --piping out the Object
END LOOP;
CLOSE local_curs; -- always do this
RETURN; -- we're now done
END RETURN_MY_ROWS;
sau khi bạn đã làm điều đó, bạn có thể sử dụng nó như vậy
SELECT * FROM TABLE(RETURN_MY_ROWS(val1, val2));
bạn có thể INSERT SELECT hoặc thậm chí CREATE TABLE ra khỏi nó, bạn có thể có nó trong tham gia .
thêm hai điều cần đề cập đến:
--ROW_RECORD_OF_CUSTOM_OBJECT is something along these lines
CREATE or REPLACE TYPE ROW_RECORD_OF_CUSTOM_OBJECT AS OBJECT
(
col1 type;
col2 type;
...
colx type;
);
và PARENT_OBJECT là một bảng của các đối tượng khác (với các định nghĩa lĩnh vực), chúng tôi chỉ cần thực hiện
create or replace TYPE PARENT_OBJECT IS TABLE OF ROW_RECORD_OF_CUSTOM_OBJECT;
nên chức năng này cần hai đối tượng để hỗ trợ nó, nhưng một là một bản ghi, cái kia là một bảng của bản ghi đó (bạn phải tạo bản ghi đầu tiên).
Tóm lại, chức năng này dễ viết, bạn cần một đối tượng con (với các trường) và đối tượng cha sẽ đặt đối tượng con đó là kiểu TABLE của đối tượng con và bạn mở bản gốc bảng cơ sở tìm nạp SQL vào một SYS_REFCURSOR (mà bạn có thể cần phải bí danh) nếu bạn đang ở trong một gói và bạn đọc từ con trỏ đó từ một vòng lặp vào các bản ghi riêng lẻ. Hàm trả về một loại PARENT_OBJECT nhưng bên trong nó gói đối tượng phụ bản ghi với các giá trị từ con trỏ.
Tôi hy vọng công trình này cho bạn (có thể có vấn đề permissioning với DBA của bạn nếu bạn muốn tạo các đối tượng và chức năng Table) */
tốt, nhưng tôi muốn để xử lý các mặt hàng độc đáo để horrible_query_1 khác biệt so với tôi xử lý các mục duy nhất cho ugly_query_2. Có thể cho biết đặt mục nào là duy nhất đối với truy vấn này không? EDIT: Các khung nhìn có thể là giải pháp tốt nhất cho SQL thuần túy. – Buttons840
Chắc chắn, bao gồm hai hoạt động đã đặt của bạn trong các truy vấn bên ngoài với các lựa chọn bao gồm các cột cố định được gọi là Nguồn, tức là 'SELECT 'horrible_query_1' AS Source, *' và 'SELECT 'ugly_query_2' AS Source, *'. Bằng cách đó, UNION của bạn sẽ cung cấp cho bạn tất cả các cột từ truy vấn của bạn cộng với mã định danh nguồn. – JamieSee
Ví dụ cuối cùng, sử dụng "with mệnh đề" đã rất hữu ích trong những năm qua kể từ khi tôi đã hỏi câu hỏi này. Những "với mệnh đề" đôi khi được gọi là biểu thức bảng chung (hoặc CTE). Đây là một số thuật ngữ hữu ích cần biết khi tìm kiếm thêm chi tiết. Các mệnh đề được thêm vào tiêu chuẩn SQL vào năm 1999 vì vậy hầu hết các cơ sở dữ liệu cần hỗ trợ chúng, ngoại trừ MySQL mà vẫn chưa thực hiện phần này của tiêu chuẩn hai mươi tuổi. – Buttons840