Hàm tham số hóa trong C++

Các hàm SQL thực thi một danh sách các câu lệnh SQL tùy ý, trả về kết quả của truy vấn cuối cùng trong danh sách. Trong trường hợp đơn giản (không đặt), hàng đầu tiên của kết quả của truy vấn cuối cùng sẽ được trả về. (Hãy nhớ rằng “hàng đầu tiên” của kết quả nhiều hàng không được xác định rõ ràng trừ khi bạn sử dụng

CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
1. ) Nếu truy vấn cuối cùng hoàn toàn không trả về hàng nào, thì giá trị null sẽ được trả về

Ngoài ra, một hàm SQL có thể được khai báo để trả về một tập hợp (nghĩa là nhiều hàng) bằng cách chỉ định kiểu trả về của hàm là

CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
2 hoặc tương đương bằng cách khai báo nó là
CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
3). Trong trường hợp này, tất cả các hàng trong kết quả của truy vấn cuối cùng đều được trả về. Thông tin chi tiết xuất hiện bên dưới

Phần thân của hàm SQL phải là danh sách các câu lệnh SQL được phân tách bằng dấu chấm phẩy. Dấu chấm phẩy sau câu lệnh cuối cùng là tùy chọn. Trừ khi hàm được khai báo để trả về

CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
4, câu lệnh cuối cùng phải là
CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
5 hoặc
CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
6,
CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
7 hoặc
CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
8 có mệnh đề
CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
9

Bất kỳ tập lệnh nào trong ngôn ngữ SQL đều có thể được đóng gói cùng nhau và được định nghĩa dưới dạng một hàm. Bên cạnh các truy vấn

CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
5, các lệnh có thể bao gồm các truy vấn sửa đổi dữ liệu (
CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
6,
CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
7 và
CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
8), cũng như các lệnh SQL khác. (Bạn không thể sử dụng các lệnh điều khiển giao dịch, e. g. ,
CREATE FUNCTION tf1 (accountno integer, debit numeric) RETURNS numeric AS $$
    UPDATE bank
        SET balance = balance - debit
        WHERE accountno = tf1.accountno;
    SELECT 1;
$$ LANGUAGE SQL;
4,
CREATE FUNCTION tf1 (accountno integer, debit numeric) RETURNS numeric AS $$
    UPDATE bank
        SET balance = balance - debit
        WHERE accountno = tf1.accountno;
    SELECT 1;
$$ LANGUAGE SQL;
5, và một số lệnh tiện ích, e. g. ,
CREATE FUNCTION tf1 (accountno integer, debit numeric) RETURNS numeric AS $$
    UPDATE bank
        SET balance = balance - debit
        WHERE accountno = tf1.accountno;
    SELECT 1;
$$ LANGUAGE SQL;
6, trong các hàm SQL. ) Tuy nhiên, lệnh cuối cùng phải là
CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
5 hoặc có mệnh đề
CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
9 trả về bất kỳ thứ gì được chỉ định làm kiểu trả về của hàm. Ngoài ra, nếu bạn muốn xác định một hàm SQL thực hiện các hành động nhưng không có giá trị hữu ích nào để trả về, bạn có thể định nghĩa nó là trả về
CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
4. Ví dụ: hàm này xóa các hàng có mức lương âm khỏi bảng
SELECT tf1(17, 100.0);
0

CREATE FUNCTION clean_emp() RETURNS void AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

SELECT clean_emp();

 clean_emp
-----------

(1 row)

Bạn cũng có thể viết điều này như một thủ tục, do đó tránh được vấn đề về kiểu trả về. Ví dụ

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();

Trong những trường hợp đơn giản như thế này, sự khác biệt giữa một hàm trả về

CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
4 và một thủ tục chủ yếu là phong cách. Tuy nhiên, các thủ tục cung cấp chức năng bổ sung như kiểm soát giao dịch không có sẵn trong các chức năng. Ngoài ra, các thủ tục là tiêu chuẩn SQL trong khi trả về
CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
4 là một phần mở rộng PostgreSQL

Cú pháp của lệnh

SELECT tf1(17, 100.0);
3 yêu cầu thân hàm được viết dưới dạng hằng chuỗi. Cách thuận tiện nhất là sử dụng trích dẫn đô la (xem phần ) cho hằng chuỗi. Nếu bạn chọn sử dụng cú pháp hằng số chuỗi trích dẫn đơn thông thường, bạn phải nhân đôi dấu trích dẫn đơn (
SELECT tf1(17, 100.0);
4) và dấu gạch chéo ngược (
SELECT tf1(17, 100.0);
5) (giả sử cú pháp chuỗi thoát) trong phần thân của hàm (xem )

38. 5. 1. Đối số cho các hàm SQL

Các đối số của hàm SQL có thể được tham chiếu trong thân hàm bằng cách sử dụng tên hoặc số. Ví dụ về cả hai phương pháp xuất hiện bên dưới

Để sử dụng tên, hãy khai báo đối số hàm là có tên, sau đó chỉ cần viết tên đó vào thân hàm. Nếu tên đối số giống với bất kỳ tên cột nào trong lệnh SQL hiện tại trong hàm, tên cột sẽ được ưu tiên. Để ghi đè điều này, hãy xác định tên đối số bằng tên của chính hàm đó, đó là

SELECT tf1(17, 100.0);
6.
SELECT tf1(17, 100.0);
7. (Nếu điều này xung đột với tên cột đủ điều kiện, một lần nữa tên cột đó sẽ thắng. Bạn có thể tránh sự mơ hồ bằng cách chọn một bí danh khác cho bảng trong lệnh SQL. )

Trong cách tiếp cận số cũ hơn, các đối số được tham chiếu bằng cú pháp

SELECT tf1(17, 100.0);
8.
SELECT tf1(17, 100.0);
9 đề cập đến đối số đầu vào đầu tiên,
CREATE FUNCTION tf1 (accountno integer, debit numeric) RETURNS numeric AS $$
    UPDATE bank
        SET balance = balance - debit
        WHERE accountno = tf1.accountno;
    SELECT balance FROM bank WHERE accountno = tf1.accountno;
$$ LANGUAGE SQL;
0 đến đối số thứ hai, v.v. Điều này sẽ hoạt động cho dù đối số cụ thể có được khai báo bằng tên hay không

Nếu một đối số thuộc loại hỗn hợp, thì ký hiệu dấu chấm, e. g. ,

CREATE FUNCTION tf1 (accountno integer, debit numeric) RETURNS numeric AS $$
    UPDATE bank
        SET balance = balance - debit
        WHERE accountno = tf1.accountno;
    SELECT balance FROM bank WHERE accountno = tf1.accountno;
$$ LANGUAGE SQL;
1.
CREATE FUNCTION tf1 (accountno integer, debit numeric) RETURNS numeric AS $$
    UPDATE bank
        SET balance = balance - debit
        WHERE accountno = tf1.accountno;
    SELECT balance FROM bank WHERE accountno = tf1.accountno;
$$ LANGUAGE SQL;
2 hoặc $1.________31_______2, có thể được sử dụng để truy cập các thuộc tính của đối số. Một lần nữa, bạn có thể cần phải xác định tên của đối số với tên hàm để tạo biểu mẫu có tên đối số rõ ràng

Đối số hàm SQL chỉ có thể được sử dụng làm giá trị dữ liệu, không phải là mã định danh. Vì vậy, ví dụ này là hợp lý

INSERT INTO mytable VALUES ($1);

nhưng điều này sẽ không làm việc

INSERT INTO $1 VALUES (42);

Ghi chú

Khả năng sử dụng tên để tham chiếu đối số hàm SQL đã được thêm vào trong PostgreSQL 9. 2. Các chức năng được sử dụng trong các máy chủ cũ hơn phải sử dụng ký hiệu

SELECT tf1(17, 100.0);
8

38. 5. 2. Các hàm SQL trên các loại cơ sở

Hàm SQL đơn giản nhất có thể không có đối số và chỉ trả về một kiểu cơ sở, chẳng hạn như

CREATE FUNCTION tf1 (accountno integer, debit numeric) RETURNS numeric AS $$
    UPDATE bank
        SET balance = balance - debit
        WHERE accountno = tf1.accountno;
    SELECT balance FROM bank WHERE accountno = tf1.accountno;
$$ LANGUAGE SQL;
5

CREATE FUNCTION one() RETURNS integer AS $$
    SELECT 1 AS result;
$$ LANGUAGE SQL;

-- Alternative syntax for string literal:
CREATE FUNCTION one() RETURNS integer AS '
    SELECT 1 AS result;
' LANGUAGE SQL;

SELECT one();

 one
-----
   1

Lưu ý rằng chúng ta đã xác định một bí danh cột trong thân hàm cho kết quả của hàm (với tên

CREATE FUNCTION tf1 (accountno integer, debit numeric) RETURNS numeric AS $$
    UPDATE bank
        SET balance = balance - debit
        WHERE accountno = tf1.accountno;
    SELECT balance FROM bank WHERE accountno = tf1.accountno;
$$ LANGUAGE SQL;
6), nhưng bí danh cột này không hiển thị bên ngoài hàm. Do đó, kết quả được dán nhãn là
CREATE FUNCTION tf1 (accountno integer, debit numeric) RETURNS numeric AS $$
    UPDATE bank
        SET balance = balance - debit
        WHERE accountno = tf1.accountno;
    SELECT balance FROM bank WHERE accountno = tf1.accountno;
$$ LANGUAGE SQL;
7 thay vì
CREATE FUNCTION tf1 (accountno integer, debit numeric) RETURNS numeric AS $$
    UPDATE bank
        SET balance = balance - debit
        WHERE accountno = tf1.accountno;
    SELECT balance FROM bank WHERE accountno = tf1.accountno;
$$ LANGUAGE SQL;
6

Gần như dễ dàng xác định các hàm SQL lấy các kiểu cơ sở làm đối số

CREATE FUNCTION add_em(x integer, y integer) RETURNS integer AS $$
    SELECT x + y;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3

Ngoài ra, chúng ta có thể bỏ qua tên cho các đối số và sử dụng các số

CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3

Đây là một chức năng hữu ích hơn, có thể được sử dụng để ghi nợ tài khoản ngân hàng

CREATE FUNCTION tf1 (accountno integer, debit numeric) RETURNS numeric AS $$
    UPDATE bank
        SET balance = balance - debit
        WHERE accountno = tf1.accountno;
    SELECT 1;
$$ LANGUAGE SQL;

Người dùng có thể thực hiện chức năng này để ghi nợ tài khoản 17 $100. 00 như sau

SELECT tf1(17, 100.0);

Trong ví dụ này, chúng tôi đã chọn tên

CREATE FUNCTION tf1 (accountno integer, debit numeric) RETURNS numeric AS $$
    UPDATE bank
        SET balance = balance - debit
        WHERE accountno = tf1.accountno;
    SELECT balance FROM bank WHERE accountno = tf1.accountno;
$$ LANGUAGE SQL;
9 cho đối số đầu tiên, nhưng tên này giống với tên của một cột trong bảng
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
00. Trong lệnh
CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
7,
CREATE FUNCTION tf1 (accountno integer, debit numeric) RETURNS numeric AS $$
    UPDATE bank
        SET balance = balance - debit
        WHERE accountno = tf1.accountno;
    SELECT balance FROM bank WHERE accountno = tf1.accountno;
$$ LANGUAGE SQL;
9 đề cập đến cột
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
03, vì vậy phải sử dụng
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
04 để đề cập đến đối số. Tất nhiên chúng ta có thể tránh điều này bằng cách sử dụng một tên khác cho đối số

Trong thực tế, người ta có thể muốn một kết quả hữu ích hơn từ hàm hơn là hằng số 1, do đó, một định nghĩa có nhiều khả năng hơn là

CREATE FUNCTION tf1 (accountno integer, debit numeric) RETURNS numeric AS $$
    UPDATE bank
        SET balance = balance - debit
        WHERE accountno = tf1.accountno;
    SELECT balance FROM bank WHERE accountno = tf1.accountno;
$$ LANGUAGE SQL;

điều chỉnh số dư và trả lại số dư mới. Điều tương tự có thể được thực hiện trong một lệnh bằng cách sử dụng

CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
9

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
0

Nếu mệnh đề

CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
5 hoặc
CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
9 cuối cùng trong một hàm SQL không trả về chính xác loại kết quả đã khai báo của hàm, PostgreSQL sẽ tự động chuyển giá trị thành loại được yêu cầu, nếu điều đó có thể thực hiện được với một phép gán ẩn hoặc gán. Nếu không, bạn phải viết một dàn diễn viên rõ ràng. Ví dụ: giả sử chúng ta muốn hàm
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
08 trước đó trả về kiểu
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
09 thay vì. Nó là đủ để viết

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
1

vì tổng

CREATE FUNCTION tf1 (accountno integer, debit numeric) RETURNS numeric AS $$
    UPDATE bank
        SET balance = balance - debit
        WHERE accountno = tf1.accountno;
    SELECT balance FROM bank WHERE accountno = tf1.accountno;
$$ LANGUAGE SQL;
5 có thể được chuyển hoàn toàn thành
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
09. (Xem Chương 10 hoặc TẠO CAST để biết thêm thông tin về quá trình truyền. )

38. 5. 3. Các hàm SQL trên các loại tổng hợp

Khi viết các hàm với các đối số kiểu hỗn hợp, chúng ta không chỉ phải xác định chúng ta muốn đối số nào mà còn phải xác định thuộc tính (trường) mong muốn của đối số đó. Ví dụ: giả sử rằng

SELECT tf1(17, 100.0);
0 là một bảng chứa dữ liệu nhân viên và do đó cũng là tên của loại tổng hợp của mỗi hàng của bảng. Đây là một hàm
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
13 tính toán tiền lương của ai đó sẽ là bao nhiêu nếu nó được nhân đôi

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
2

Lưu ý việc sử dụng cú pháp

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
14 để chọn một trường của giá trị hàng đối số. Cũng lưu ý cách gọi lệnh
CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
5 sử dụng
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
16
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
17 để chọn toàn bộ hàng hiện tại của bảng làm giá trị tổng hợp. Thay vào đó, hàng của bảng có thể được tham chiếu chỉ bằng tên bảng, như thế này

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
3

nhưng cách sử dụng này không được dùng nữa vì nó dễ bị nhầm lẫn. (Xem để biết chi tiết về hai ký hiệu này cho giá trị tổng hợp của một hàng trong bảng. )

Đôi khi, thật tiện lợi khi xây dựng một giá trị đối số tổng hợp khi đang di chuyển. Điều này có thể được thực hiện với cấu trúc

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
18. Ví dụ: chúng ta có thể điều chỉnh dữ liệu được chuyển đến hàm

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
4

Cũng có thể xây dựng hàm trả về kiểu tổng hợp. Đây là một ví dụ về hàm trả về một hàng

SELECT tf1(17, 100.0);
0

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
5

Trong ví dụ này, chúng tôi đã chỉ định từng thuộc tính với một giá trị không đổi, nhưng bất kỳ tính toán nào cũng có thể được thay thế cho các hằng số này

Lưu ý hai điều quan trọng về việc xác định chức năng

  • Thứ tự danh sách chọn trong truy vấn phải hoàn toàn giống với thứ tự các cột xuất hiện trong kiểu tổng hợp. (Việc đặt tên cột, như chúng ta đã làm ở trên, không liên quan đến hệ thống. )

  • Chúng ta phải đảm bảo loại của mỗi biểu thức có thể được chuyển thành loại của cột tương ứng của loại tổng hợp. Nếu không, chúng tôi sẽ gặp lỗi như thế này

    CREATE PROCEDURE clean_emp() AS '
        DELETE FROM emp
            WHERE salary < 0;
    ' LANGUAGE SQL;
    
    CALL clean_emp();
    
    6

    Cũng giống như trường hợp kiểu cơ sở, hệ thống sẽ không tự động chèn các phép gán rõ ràng, mà chỉ chèn các phép gán ẩn hoặc gán

Một cách khác để xác định chức năng tương tự là

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
7

Ở đây chúng tôi đã viết một

CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
5 chỉ trả về một cột duy nhất của loại tổng hợp chính xác. Điều này không thực sự tốt hơn trong tình huống này, nhưng nó là một giải pháp thay thế hữu ích trong một số trường hợp — ví dụ: nếu chúng ta cần tính toán kết quả bằng cách gọi một hàm khác trả về giá trị tổng hợp mong muốn. Một ví dụ khác là nếu chúng ta đang cố gắng viết một hàm trả về một miền theo kiểu hỗn hợp, chứ không phải kiểu hỗn hợp đơn giản, thì luôn cần phải viết nó dưới dạng trả về một cột, vì không có cách nào để gây ra sự ép buộc của

Chúng ta có thể gọi hàm này trực tiếp bằng cách sử dụng nó trong một biểu thức giá trị

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
8

hoặc bằng cách gọi nó là một chức năng bảng

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
9

Cách thứ hai được mô tả đầy đủ hơn trong

Khi bạn sử dụng một hàm trả về một loại kết hợp, bạn có thể chỉ muốn một trường (thuộc tính) từ kết quả của nó. Bạn có thể làm điều đó với cú pháp như thế này

INSERT INTO mytable VALUES ($1);
0

Các dấu ngoặc đơn bổ sung là cần thiết để giữ cho trình phân tích cú pháp khỏi bị nhầm lẫn. Nếu bạn cố gắng làm điều đó mà không có chúng, bạn sẽ nhận được một cái gì đó như thế này

INSERT INTO mytable VALUES ($1);
1

Một tùy chọn khác là sử dụng ký hiệu chức năng để trích xuất một thuộc tính

INSERT INTO mytable VALUES ($1);
2

Như đã giải thích trong phần , ký hiệu trường và ký hiệu chức năng là tương đương

Một cách khác để sử dụng hàm trả về loại tổng hợp là chuyển kết quả cho một hàm khác chấp nhận loại hàng chính xác làm đầu vào

INSERT INTO mytable VALUES ($1);
3

38. 5. 4. Hàm SQL với tham số đầu ra

Một cách khác để mô tả kết quả của một hàm là xác định nó với các tham số đầu ra, như trong ví dụ này

INSERT INTO mytable VALUES ($1);
4

Phiên bản này về cơ bản không khác với phiên bản của

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
08 được hiển thị trong. Giá trị thực của các tham số đầu ra là chúng cung cấp một cách thuận tiện để xác định các hàm trả về một số cột. Ví dụ,

INSERT INTO mytable VALUES ($1);
5

Điều cơ bản đã xảy ra ở đây là chúng ta đã tạo một kiểu hỗn hợp ẩn danh cho kết quả của hàm. Ví dụ trên có kết quả cuối cùng giống như

INSERT INTO mytable VALUES ($1);
6

nhưng không phải bận tâm với định nghĩa loại hỗn hợp riêng biệt thường rất tiện lợi. Lưu ý rằng các tên được gắn với các tham số đầu ra không chỉ là trang trí mà còn xác định tên cột của loại hỗn hợp ẩn danh. (Nếu bạn bỏ qua tên cho tham số đầu ra, hệ thống sẽ tự chọn tên. )

Lưu ý rằng các tham số đầu ra không được bao gồm trong danh sách đối số gọi khi gọi một hàm như vậy từ SQL. Điều này là do PostgreSQL chỉ xem xét các tham số đầu vào để xác định chữ ký gọi của hàm. Điều đó cũng có nghĩa là chỉ các tham số đầu vào mới quan trọng khi tham chiếu hàm cho các mục đích chẳng hạn như loại bỏ nó. Chúng ta có thể bỏ chức năng trên với một trong hai

INSERT INTO mytable VALUES ($1);
7

Các tham số có thể được đánh dấu là

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
22 (mặc định),
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
23,
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
24 hoặc
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
25. Tham số
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
24 đóng vai trò vừa là tham số đầu vào (một phần của danh sách đối số gọi) vừa là tham số đầu ra (một phần của loại bản ghi kết quả). Tham số
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
25 là tham số đầu vào, nhưng được xử lý đặc biệt như mô tả bên dưới

38. 5. 5. Thủ tục SQL với các tham số đầu ra

Các tham số đầu ra cũng được hỗ trợ trong các thủ tục, nhưng chúng hoạt động hơi khác so với các hàm. Trong các lệnh

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
28, tham số đầu ra phải được đưa vào danh sách đối số. Ví dụ: thói quen ghi nợ tài khoản ngân hàng từ trước đó có thể được viết như thế này

INSERT INTO mytable VALUES ($1);
8

Để gọi thủ tục này, phải bao gồm một đối số phù hợp với tham số

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
23. Đó là thông lệ để viết
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
30

INSERT INTO mytable VALUES ($1);
9

Nếu bạn viết cái gì khác, nó phải là một biểu thức hoàn toàn cưỡng chế đối với kiểu khai báo của tham số, giống như đối với tham số đầu vào. Tuy nhiên, lưu ý rằng một biểu thức như vậy sẽ không được đánh giá

38. 5. 6. Các hàm SQL với số lượng đối số thay đổi

Các hàm SQL có thể được khai báo để chấp nhận số lượng đối số thay đổi, miễn là tất cả các đối số "tùy chọn" có cùng kiểu dữ liệu. Các đối số tùy chọn sẽ được chuyển đến hàm dưới dạng một mảng. Hàm được khai báo bằng cách đánh dấu tham số cuối cùng là

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
25; . Ví dụ

INSERT INTO $1 VALUES (42);
0

Thực tế, tất cả các đối số thực tại hoặc ngoài vị trí

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
25 được tập hợp thành một mảng một chiều, như thể bạn đã viết

INSERT INTO $1 VALUES (42);
1

Tuy nhiên, bạn thực sự không thể viết như vậy — hoặc ít nhất, nó sẽ không khớp với định nghĩa hàm này. Một tham số được đánh dấu

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
25 khớp với một hoặc nhiều lần xuất hiện của loại phần tử của nó, không phải loại của chính nó

Đôi khi rất hữu ích khi có thể chuyển một mảng đã được tạo sẵn cho một hàm biến thiên; . Ngoài ra, đây là cách an toàn duy nhất để gọi hàm biến thiên được tìm thấy trong lược đồ cho phép người dùng không đáng tin cậy tạo đối tượng; . 3. Bạn có thể làm điều này bằng cách chỉ định

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
25 trong cuộc gọi

INSERT INTO $1 VALUES (42);
2

Điều này ngăn việc mở rộng tham số biến đổi của hàm thành loại phần tử của nó, do đó cho phép giá trị đối số mảng khớp bình thường.

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
25 chỉ có thể được đính kèm với đối số thực tế cuối cùng của lệnh gọi hàm

Ví dụ, chỉ định

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
25 trong lệnh gọi cũng là cách duy nhất để chuyển một mảng trống sang một hàm biến thiên

INSERT INTO $1 VALUES (42);
3

Chỉ cần viết

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
37 không hoạt động vì tham số biến đổi phải khớp với ít nhất một đối số thực tế. (Bạn có thể định nghĩa một hàm thứ hai cũng có tên là
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
38, không có tham số, nếu bạn muốn cho phép các cuộc gọi như vậy. )

Các tham số phần tử mảng được tạo từ một tham số biến đổi được coi là không có bất kỳ tên riêng nào. Điều này có nghĩa là không thể gọi một hàm biến thiên bằng cách sử dụng các đối số đã đặt tên (Phần 4. 3), trừ khi bạn chỉ định

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
25. Ví dụ, điều này sẽ làm việc

INSERT INTO $1 VALUES (42);
4

nhưng không phải những

INSERT INTO $1 VALUES (42);
5

38. 5. 7. Các hàm SQL với các giá trị mặc định cho các đối số

Các chức năng có thể được khai báo với các giá trị mặc định cho một số hoặc tất cả các đối số đầu vào. Các giá trị mặc định được chèn vào bất cứ khi nào hàm được gọi với không đủ đối số thực tế. Vì các đối số chỉ có thể được bỏ qua ở cuối danh sách đối số thực tế, nên tất cả các tham số sau một tham số có giá trị mặc định cũng phải có giá trị mặc định. (Mặc dù việc sử dụng ký hiệu đối số được đặt tên có thể cho phép nới lỏng hạn chế này, nó vẫn được thực thi để ký hiệu đối số vị trí hoạt động hợp lý. ) Cho dù bạn có sử dụng nó hay không, khả năng này tạo ra nhu cầu đề phòng khi gọi các chức năng trong cơ sở dữ liệu mà một số người dùng không tin tưởng những người dùng khác; . 3

Ví dụ

INSERT INTO $1 VALUES (42);
6

Dấu hiệu

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
40 cũng có thể được sử dụng thay cho từ khóa
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
41

38. 5. 8. Các hàm SQL dưới dạng nguồn bảng

Tất cả các hàm SQL có thể được sử dụng trong mệnh đề

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
42 của một truy vấn, nhưng nó đặc biệt hữu ích cho các hàm trả về các kiểu kết hợp. Nếu hàm được xác định để trả về một kiểu cơ sở, thì hàm bảng sẽ tạo ra một bảng một cột. Nếu hàm được xác định để trả về một loại hỗn hợp, thì hàm bảng sẽ tạo một cột cho từng thuộc tính của loại hỗn hợp

Đây là một ví dụ

INSERT INTO $1 VALUES (42);
7

Như ví dụ cho thấy, chúng ta có thể làm việc với các cột trong kết quả của hàm giống như khi chúng là các cột của một bảng thông thường

Lưu ý rằng chúng tôi chỉ có một hàng trong hàm. Điều này là do chúng tôi đã không sử dụng

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
43. Điều đó được mô tả trong phần tiếp theo

38. 5. 9. Các hàm SQL trả về các tập hợp

Khi một hàm SQL được khai báo là trả về

CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
2, thì truy vấn cuối cùng của hàm được thực thi cho đến khi hoàn thành và mỗi hàng mà nó xuất ra được trả về dưới dạng một phần tử của tập kết quả

Tính năng này thường được sử dụng khi gọi hàm trong mệnh đề

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
42. Trong trường hợp này, mỗi hàng được hàm trả về sẽ trở thành một hàng của bảng mà truy vấn nhìn thấy. Ví dụ: giả sử rằng bảng
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
46 có cùng nội dung như trên và chúng tôi nói

INSERT INTO $1 VALUES (42);
8

Sau đó, chúng tôi sẽ nhận được

INSERT INTO $1 VALUES (42);
9

Cũng có thể trả về nhiều hàng với các cột được xác định bởi các tham số đầu ra, như thế này

CREATE FUNCTION one() RETURNS integer AS $$
    SELECT 1 AS result;
$$ LANGUAGE SQL;

-- Alternative syntax for string literal:
CREATE FUNCTION one() RETURNS integer AS '
    SELECT 1 AS result;
' LANGUAGE SQL;

SELECT one();

 one
-----
   1
0

Điểm mấu chốt ở đây là bạn phải viết

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
47 để chỉ ra rằng hàm trả về nhiều hàng thay vì chỉ một. Nếu chỉ có một tham số đầu ra, hãy viết loại của tham số đó thay vì
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
48

Việc xây dựng kết quả của một truy vấn thường hữu ích bằng cách gọi hàm trả về tập hợp nhiều lần, với các tham số cho mỗi lần gọi đến từ các hàng liên tiếp của bảng hoặc truy vấn con. Cách ưa thích để làm điều này là sử dụng từ khóa

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
49, được mô tả trong. Dưới đây là một ví dụ sử dụng hàm trả về tập hợp để liệt kê các phần tử của cấu trúc cây

CREATE FUNCTION one() RETURNS integer AS $$
    SELECT 1 AS result;
$$ LANGUAGE SQL;

-- Alternative syntax for string literal:
CREATE FUNCTION one() RETURNS integer AS '
    SELECT 1 AS result;
' LANGUAGE SQL;

SELECT one();

 one
-----
   1
1

Ví dụ này không thực hiện bất cứ điều gì mà chúng ta không thể thực hiện với một phép nối đơn giản, nhưng trong các tính toán phức tạp hơn, tùy chọn đưa một số công việc vào một hàm có thể khá thuận tiện

Các hàm trả về tập hợp cũng có thể được gọi trong danh sách chọn của truy vấn. Đối với mỗi hàng mà truy vấn tự tạo, hàm trả về tập hợp được gọi và một hàng đầu ra được tạo cho mỗi phần tử trong tập kết quả của hàm. Ví dụ trước cũng có thể được thực hiện với các truy vấn như thế này

CREATE FUNCTION one() RETURNS integer AS $$
    SELECT 1 AS result;
$$ LANGUAGE SQL;

-- Alternative syntax for string literal:
CREATE FUNCTION one() RETURNS integer AS '
    SELECT 1 AS result;
' LANGUAGE SQL;

SELECT one();

 one
-----
   1
2

Trong

CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
5 cuối cùng, lưu ý rằng không có hàng đầu ra nào xuất hiện cho
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
51,
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
52, v.v. Điều này xảy ra vì
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
53 trả về một tập hợp trống cho các đối số đó, vì vậy không có hàng kết quả nào được tạo. Đây là hành vi tương tự như chúng ta nhận được từ phép nối bên trong với kết quả của hàm khi sử dụng cú pháp
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
49

Hành vi của PostgreSQL đối với một hàm trả về tập hợp trong danh sách chọn của truy vấn gần như hoàn toàn giống như thể hàm trả về tập hợp đã được viết trong một mục mệnh đề

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
55 thay thế. Ví dụ,

CREATE FUNCTION one() RETURNS integer AS $$
    SELECT 1 AS result;
$$ LANGUAGE SQL;

-- Alternative syntax for string literal:
CREATE FUNCTION one() RETURNS integer AS '
    SELECT 1 AS result;
' LANGUAGE SQL;

SELECT one();

 one
-----
   1
3

gần như tương đương với

CREATE FUNCTION one() RETURNS integer AS $$
    SELECT 1 AS result;
$$ LANGUAGE SQL;

-- Alternative syntax for string literal:
CREATE FUNCTION one() RETURNS integer AS '
    SELECT 1 AS result;
' LANGUAGE SQL;

SELECT one();

 one
-----
   1
4

Nó sẽ hoàn toàn giống nhau, ngoại trừ trong ví dụ cụ thể này, người lập kế hoạch có thể chọn đặt

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
56 ở bên ngoài của phép nối vòng lặp lồng nhau, vì
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
56 không có sự phụ thuộc bên thực sự vào
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
58. Điều đó sẽ dẫn đến một thứ tự hàng đầu ra khác nhau. Các hàm trả về tập hợp trong danh sách chọn luôn được đánh giá như thể chúng ở bên trong liên kết vòng lặp lồng nhau với phần còn lại của mệnh đề
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
42, sao cho (các) hàm được chạy cho đến khi hoàn thành trước hàng tiếp theo từ
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
42

Nếu có nhiều hơn một hàm trả về tập hợp trong danh sách lựa chọn của truy vấn, hành vi này tương tự như những gì bạn nhận được từ việc đưa các hàm vào một mục mệnh đề

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
61
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
42. Đối với mỗi hàng từ truy vấn cơ bản, có một hàng đầu ra sử dụng kết quả đầu tiên từ mỗi hàm, sau đó là một hàng đầu ra sử dụng kết quả thứ hai, v.v. Nếu một số hàm trả về tập hợp tạo ra ít đầu ra hơn các hàm khác, thì các giá trị null sẽ được thay thế cho dữ liệu bị thiếu, sao cho tổng số hàng được tạo ra cho một hàng bên dưới giống như đối với hàm trả về tập hợp tạo ra nhiều đầu ra nhất. Do đó, các hàm trả về tập hợp chạy “theo từng bước” cho đến khi tất cả chúng cạn kiệt, sau đó quá trình thực thi tiếp tục với hàng bên dưới tiếp theo

Các hàm trả về tập hợp có thể được lồng trong một danh sách chọn, mặc dù điều đó không được phép trong các mục của mệnh đề

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
42. Trong những trường hợp như vậy, mỗi cấp độ lồng ghép được xử lý riêng biệt, như thể nó là một mục
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
61 riêng biệt. Ví dụ, trong

CREATE FUNCTION one() RETURNS integer AS $$
    SELECT 1 AS result;
$$ LANGUAGE SQL;

-- Alternative syntax for string literal:
CREATE FUNCTION one() RETURNS integer AS '
    SELECT 1 AS result;
' LANGUAGE SQL;

SELECT one();

 one
-----
   1
5

các hàm trả về tập hợp

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
65,
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
66 và
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
67 sẽ được chạy theo bước khóa cho mỗi hàng của
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
58, sau đó
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
69 và
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
70 sẽ được áp dụng theo bước khóa cho mỗi hàng được tạo bởi các hàm thấp hơn

Không thể sử dụng các hàm trả về tập hợp trong các cấu trúc đánh giá có điều kiện, chẳng hạn như

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
71 hoặc
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
72. Ví dụ, xem xét

CREATE FUNCTION one() RETURNS integer AS $$
    SELECT 1 AS result;
$$ LANGUAGE SQL;

-- Alternative syntax for string literal:
CREATE FUNCTION one() RETURNS integer AS '
    SELECT 1 AS result;
' LANGUAGE SQL;

SELECT one();

 one
-----
   1
6

Có vẻ như điều này sẽ tạo ra năm lần lặp lại các hàng đầu vào có

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
73 và một lần lặp lại duy nhất của những hàng không có; . Để giảm nhầm lẫn, thay vào đó, các trường hợp như vậy sẽ tạo ra lỗi thời gian phân tích cú pháp

Ghi chú

Nếu lệnh cuối cùng của một hàm là

CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
6,
CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
7 hoặc
CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
8 với
CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
9, thì lệnh đó sẽ luôn được thực thi cho đến khi hoàn thành, ngay cả khi hàm không được khai báo với
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
43 hoặc truy vấn gọi không tìm nạp tất cả các hàng kết quả. Bất kỳ hàng bổ sung nào được tạo bởi mệnh đề
CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
9 đều bị loại bỏ một cách âm thầm, nhưng các sửa đổi bảng đã ra lệnh vẫn xảy ra (và tất cả đều được hoàn thành trước khi trở về từ hàm)

Ghi chú

Trước PostgreSQL 10, việc đặt nhiều hơn một hàm trả về tập hợp trong cùng một danh sách chọn không hoạt động hợp lý lắm trừ khi chúng luôn tạo ra số lượng hàng bằng nhau. Mặt khác, những gì bạn nhận được là một số hàng đầu ra bằng bội số chung nhỏ nhất của số hàng được tạo bởi các hàm trả về tập hợp. Ngoài ra, các hàm trả về tập hợp lồng nhau không hoạt động như mô tả ở trên; . Ngoài ra, thực thi có điều kiện (các hàm trả về tập hợp bên trong

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
71, v.v. ) trước đây đã được cho phép, mọi thứ thậm chí còn phức tạp hơn. Nên sử dụng cú pháp
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
49 khi viết các truy vấn cần hoạt động trong các phiên bản PostgreSQL cũ hơn, vì điều đó sẽ cho kết quả nhất quán trên các phiên bản khác nhau. Nếu bạn có truy vấn dựa trên việc thực thi có điều kiện của hàm trả về tập hợp, bạn có thể khắc phục vấn đề đó bằng cách chuyển kiểm tra có điều kiện sang hàm trả về tập hợp tùy chỉnh. Ví dụ,

CREATE FUNCTION one() RETURNS integer AS $$
    SELECT 1 AS result;
$$ LANGUAGE SQL;

-- Alternative syntax for string literal:
CREATE FUNCTION one() RETURNS integer AS '
    SELECT 1 AS result;
' LANGUAGE SQL;

SELECT one();

 one
-----
   1
7

có thể trở thành

CREATE FUNCTION one() RETURNS integer AS $$
    SELECT 1 AS result;
$$ LANGUAGE SQL;

-- Alternative syntax for string literal:
CREATE FUNCTION one() RETURNS integer AS '
    SELECT 1 AS result;
' LANGUAGE SQL;

SELECT one();

 one
-----
   1
8

Công thức này sẽ hoạt động giống nhau trong tất cả các phiên bản PostgreSQL

38. 5. 10. Các hàm SQL trả về CREATE PROCEDURE clean_emp() AS ' DELETE FROM emp WHERE salary < 0; ' LANGUAGE SQL; CALL clean_emp(); 85

Có một cách khác để khai báo một hàm là trả về một tập hợp, đó là sử dụng cú pháp

CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
3). Điều này tương đương với việc sử dụng một hoặc nhiều tham số
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
23 cộng với việc đánh dấu hàm là trả về
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
88 (hoặc một loại tham số đầu ra
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
43, nếu phù hợp). Ký hiệu này được chỉ định trong các phiên bản gần đây của tiêu chuẩn SQL và do đó có thể dễ mang theo hơn là sử dụng
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
43

Ví dụ: ví dụ tổng và tích trước đó cũng có thể được thực hiện theo cách này

CREATE FUNCTION one() RETURNS integer AS $$
    SELECT 1 AS result;
$$ LANGUAGE SQL;

-- Alternative syntax for string literal:
CREATE FUNCTION one() RETURNS integer AS '
    SELECT 1 AS result;
' LANGUAGE SQL;

SELECT one();

 one
-----
   1
9

Không được phép sử dụng các tham số rõ ràng

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
23 hoặc
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
24 với ký hiệu
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
93 — bạn phải đặt tất cả các cột đầu ra trong danh sách
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
85

38. 5. 11. Hàm SQL đa hình

Các hàm SQL có thể được khai báo để chấp nhận và trả về các kiểu đa hình được mô tả trong. Đây là một hàm đa hình

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
95 xây dựng một mảng từ hai phần tử kiểu dữ liệu tùy ý

CREATE FUNCTION add_em(x integer, y integer) RETURNS integer AS $$
    SELECT x + y;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
0

Lưu ý việc sử dụng typecast

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
96 để xác định rằng đối số thuộc loại
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
97. Điều này là bắt buộc nếu đối số chỉ là một chuỗi ký tự, vì nếu không, nó sẽ được coi là loại
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
98 và mảng của
CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
98 không phải là loại hợp lệ. Nếu không có typecast, bạn sẽ gặp lỗi như thế này

CREATE FUNCTION add_em(x integer, y integer) RETURNS integer AS $$
    SELECT x + y;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
1

Với

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
95 được khai báo như trên, bạn phải cung cấp hai đối số có cùng kiểu dữ liệu; . Vì vậy, ví dụ này không hoạt động

CREATE FUNCTION add_em(x integer, y integer) RETURNS integer AS $$
    SELECT x + y;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
2

Một cách tiếp cận khác là sử dụng họ các kiểu đa hình “chung”, cho phép hệ thống cố gắng xác định một kiểu chung phù hợp

CREATE FUNCTION add_em(x integer, y integer) RETURNS integer AS $$
    SELECT x + y;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
3

Bởi vì các quy tắc cho độ phân giải loại phổ biến mặc định chọn loại

CREATE PROCEDURE clean_emp() AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

CALL clean_emp();
97 khi tất cả đầu vào là loại không xác định, điều này cũng hoạt động

CREATE FUNCTION add_em(x integer, y integer) RETURNS integer AS $$
    SELECT x + y;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
4

Được phép có các đối số đa hình với kiểu trả về cố định, nhưng ngược lại thì không. Ví dụ

CREATE FUNCTION add_em(x integer, y integer) RETURNS integer AS $$
    SELECT x + y;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
5

Tính đa hình có thể được sử dụng với các hàm có đối số đầu ra. Ví dụ

CREATE FUNCTION add_em(x integer, y integer) RETURNS integer AS $$
    SELECT x + y;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
6

Đa hình cũng có thể được sử dụng với các hàm variadic. Ví dụ

CREATE FUNCTION add_em(x integer, y integer) RETURNS integer AS $$
    SELECT x + y;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
7

38. 5. 12. Các hàm SQL với các đối chiếu

Khi một hàm SQL có một hoặc nhiều tham số thuộc loại dữ liệu có thể đối chiếu, thì một đối chiếu được xác định cho mỗi lệnh gọi hàm tùy thuộc vào các đối chiếu được gán cho các đối số thực tế, như được mô tả trong Phần 24. 2. Nếu một đối chiếu được xác định thành công (i. e. , không có xung đột đối chiếu ngầm giữa các đối số) thì tất cả các tham số có thể đối chiếu được coi là có đối chiếu ngầm. Điều này sẽ ảnh hưởng đến hành vi của các hoạt động nhạy cảm đối chiếu trong chức năng. Ví dụ: sử dụng hàm

INSERT INTO mytable VALUES ($1);
02 được mô tả ở trên, kết quả của

CREATE FUNCTION add_em(x integer, y integer) RETURNS integer AS $$
    SELECT x + y;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
8

sẽ phụ thuộc vào đối chiếu mặc định của cơ sở dữ liệu. Ở ngôn ngữ

INSERT INTO mytable VALUES ($1);
03, kết quả sẽ là
INSERT INTO mytable VALUES ($1);
04, nhưng ở nhiều ngôn ngữ khác, kết quả sẽ là
INSERT INTO mytable VALUES ($1);
05. Đối chiếu để sử dụng có thể bị ép buộc bằng cách thêm mệnh đề
INSERT INTO mytable VALUES ($1);
06 vào bất kỳ đối số nào, ví dụ

CREATE FUNCTION add_em(x integer, y integer) RETURNS integer AS $$
    SELECT x + y;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
9

Ngoài ra, nếu bạn muốn một hàm hoạt động với một đối chiếu cụ thể bất kể nó được gọi với cái gì, hãy chèn các mệnh đề

INSERT INTO mytable VALUES ($1);
06 nếu cần trong định nghĩa hàm. Phiên bản
INSERT INTO mytable VALUES ($1);
02 này sẽ luôn sử dụng ngôn ngữ
INSERT INTO mytable VALUES ($1);
09 để so sánh các chuỗi

CREATE FUNCTION add_em(integer, integer) RETURNS integer AS $$
    SELECT $1 + $2;
$$ LANGUAGE SQL;

SELECT add_em(1, 2) AS answer;

 answer
--------
      3
0

Nhưng lưu ý rằng điều này sẽ gây ra lỗi nếu áp dụng cho loại dữ liệu không thể đối chiếu

Nếu không thể xác định đối chiếu chung giữa các đối số thực tế, thì hàm SQL coi các tham số của nó là đối chiếu mặc định của kiểu dữ liệu (thường là đối chiếu mặc định của cơ sở dữ liệu, nhưng có thể khác đối với tham số của loại miền)

Hành vi của các tham số có thể đối chiếu có thể được coi là một dạng đa hình hạn chế, chỉ áp dụng cho các loại dữ liệu văn bản