TL; DR :bạn can chọn từ các hàm (có giá trị bảng) hoặc từ bất kỳ loại hàm nào trong PostgreSQL. Nhưng không phải từ các thủ tục được lưu trữ.
Đây là một lời giải thích "trực quan", hơi bất khả tri về cơ sở dữ liệu, vì tôi tin rằng SQL và nhiều phương ngữ của nó quá giống một ngôn ngữ / khái niệm phát triển hữu cơ để có một lời giải thích cơ bản, "khoa học" cho điều này.
Thủ tục so với Chức năng, về mặt lịch sử
Tôi không thực sự thấy điểm của việc lựa chọn từ các thủ tục được lưu trữ, nhưng tôi có thành kiến với nhiều năm kinh nghiệm và chấp nhận hiện trạng và chắc chắn tôi thấy sự khác biệt giữa thủ tục như thế nào và chức năng có thể gây nhầm lẫn và người ta sẽ ước chúng linh hoạt và mạnh mẽ hơn như thế nào. Cụ thể là trong SQL Server, Sybase hoặc MySQL, các thủ tục có thể trả về một số bộ kết quả / số lượng cập nhật tùy ý, mặc dù điều này không giống với một hàm trả về kiểu được xác định rõ.
Hãy coi các thủ tục là quy trình bắt buộc (có tác dụng phụ) và có chức năng như thói quen thuần túy mà không có tác dụng phụ. A SELECT
bản thân câu lệnh cũng là "pure" không có tác dụng phụ (ngoài các hiệu ứng khóa tiềm ẩn), vì vậy, thật hợp lý khi coi các hàm là loại quy trình duy nhất có thể được sử dụng trong SELECT
tuyên bố.
Trên thực tế, hãy nghĩ về các hàm như là các quy trình có các ràng buộc mạnh mẽ về hành vi, trong khi các thủ tục được phép thực thi các chương trình tùy ý.
Ngôn ngữ 4GL so với 3GL
Một cách khác để xem xét vấn đề này là từ quan điểm của SQL là một ngôn ngữ lập trình thế hệ thứ 4 (4GL) . Một 4GL chỉ có thể hoạt động hợp lý nếu nó bị hạn chế nhiều về những gì nó có thể làm. Biểu thức bảng phổ biến đã tạo SQL turing-complete , vâng, nhưng bản chất khai báo của SQL vẫn ngăn nó trở thành một ngôn ngữ có mục đích chung từ góc độ thực tế, hàng ngày.
Các thủ tục được lưu trữ là một cách để vượt qua hạn chế này. Đôi khi, bạn muốn hoàn thành turing và thực dụng. Vì vậy, các thủ tục được lưu trữ là bắt buộc, có tác dụng phụ, mang tính chất giao dịch, v.v.
Các hàm được lưu trữ là một cách thông minh để giới thiệu một số Các tính năng 3GL / ngôn ngữ thủ tục vào thế giới 4GL thuần khiết hơn với mức giá là cấm các tác dụng phụ bên trong chúng (trừ khi bạn muốn mở hộp của pandora và có SELECT
hoàn toàn không thể đoán trước được câu lệnh).
Thực tế là một số cơ sở dữ liệu cho phép các thủ tục được lưu trữ của chúng trả về số lượng tùy ý của bộ kết quả / con trỏ là một đặc điểm của hành vi cho phép tùy ý của chúng, bao gồm cả các tác dụng phụ. Về nguyên tắc, không có gì tôi đã nói sẽ ngăn chặn hành vi cụ thể này cũng trong các hàm được lưu trữ, nhưng sẽ rất không thực tế và khó quản lý nếu chúng được phép làm như vậy trong ngữ cảnh của SQL, ngôn ngữ 4GL.
Như vậy:
- Các thủ tục có thể gọi các thủ tục, bất kỳ hàm nào và SQL
- Các hàm "thuần túy" có thể gọi các hàm "thuần túy" và SQL
- SQL có thể gọi các hàm "thuần túy" và SQL
Nhưng:
- Các hàm "thuần túy" gọi các thủ tục trở thành các hàm "không tinh khiết" (như các thủ tục)
Và:
- SQL không thể gọi các thủ tục
- SQL không thể gọi các hàm "không tinh khiết"
Ví dụ về các hàm có giá trị bảng "thuần túy":
Dưới đây là một số ví dụ về việc sử dụng các hàm "thuần túy" có giá trị bảng:
Oracle
CREATE TYPE numbers AS TABLE OF number(10);
/
CREATE OR REPLACE FUNCTION my_function (a number, b number)
RETURN numbers
IS
BEGIN
return numbers(a, b);
END my_function;
/
Và sau đó:
SELECT * FROM TABLE (my_function(1, 2))
Máy chủ SQL
CREATE FUNCTION my_function(@v1 INTEGER, @v2 INTEGER)
RETURNS @out_table TABLE (
column_value INTEGER
)
AS
BEGIN
INSERT @out_table
VALUES (@v1), (@v2)
RETURN
END
Và sau đó
SELECT * FROM my_function(1, 2)
PostgreSQL
Hãy để tôi nói về PostgreSQL.
PostgreSQL thật tuyệt vời và do đó là một ngoại lệ. Nó cũng kỳ lạ và có lẽ 50% tính năng của nó không nên được sử dụng trong sản xuất. Nó chỉ hỗ trợ "chức năng", không phải "thủ tục", nhưng những chức năng đó có thể hoạt động như bất cứ thứ gì. Kiểm tra những điều sau:
CREATE OR REPLACE FUNCTION wow ()
RETURNS SETOF INT
AS $$
BEGIN
CREATE TABLE boom (i INT);
RETURN QUERY
INSERT INTO boom VALUES (1)
RETURNING *;
END;
$$ LANGUAGE plpgsql;
Tác dụng phụ:
- Một bảng đã được tạo
- Một bản ghi đã được chèn
Tuy nhiên:
SELECT * FROM wow();
Lợi nhuận
wow
---
1