Có chỗ cho những cải tiến:
CREATE OR REPLACE FUNCTION report_get_countries_new (starts_with text
, ends_with text = NULL)
RETURNS SETOF lookups.countries AS
$func$
DECLARE
sql text := 'SELECT * FROM lookups.countries WHERE country_name >= $1';
BEGIN
IF ends_with IS NOT NULL THEN
sql := sql || ' AND country_name <= $2';
END IF;
RETURN QUERY EXECUTE sql
USING starts_with, ends_with;
END
$func$ LANGUAGE plpgsql;
-- the rest is default settings
Những điểm chính
-
PostgreSQL 8.4 đã giới thiệu
USING
mệnh đề choEXECUTE
, điều này hữu ích vì một số lý do. Tóm tắt lại trong sách hướng dẫn:Chuỗi lệnh có thể sử dụng các giá trị tham số, được tham chiếu trong lệnh dưới dạng
$1, $2
, v.v. Các ký hiệu này đề cập đến các giá trị được cung cấp trongUSING
mệnh đề. Phương pháp này thường thích hợp hơn khi chèn các datavalues vào chuỗi lệnh dưới dạng văn bản:nó tránh được việc chuyển đổi các giá trị thành văn bản và ngược lại trong thời gian chạy và nó ít bị tấn công SQL-injection hơn nhiều vì không cần trích dẫn hoặc thoát.IOW, nó an toàn và nhanh hơn so với việc xây dựng một chuỗi truy vấn với biểu diễn văn bản của các tham số, ngay cả khi được làm sạch bằng
quote_literal()
.
Lưu ý rằng$1, $2
trong chuỗi truy vấn, hãy tham chiếu đến các giá trị được cung cấp trongUSING
mệnh đề, không vào các tham số chức năng. -
Trong khi bạn trả về
SELECT * FROM lookups.countries
, bạn có thể đơn giản hóaRETURN
khai báo như đã chứng minh:RETURNS SETOF lookups.countries
Trong PostgreSQL, có một kiểu kết hợp được xác định tự động cho mọi bảng. Sử dụng nó. Hiệu quả là chức năng phụ thuộc vào loại và bạn sẽ nhận được thông báo lỗi nếu bạn cố gắng thay đổi bảng. Bỏ và tạo lại hàm trong trường hợp như vậy.
Điều này có thể mong muốn hoặc không - nói chung là như vậy! Bạn muốn được thông báo về các tác dụng phụ nếu bạn thay đổi bảng. Theo cách bạn có, hàm của bạn sẽ bị hỏng một cách im lặng và tạo ra một ngoại lệ trong lần gọi tiếp theo.
-
Nếu bạn cung cấp mặc định rõ ràng đối với tham số thứ hai trong khai báo như đã trình bày, bạn có thể (nhưng không cần phải) đơn giản hóa lệnh gọi trong trường hợp bạn không muốn đặt giới hạn trên với
ends_with
.SELECT * FROM report_get_countries_new('Zaire');
thay vì:
SELECT * FROM report_get_countries_new('Zaire', NULL);
Hãy lưu ý về việc quá tải hàm trong ngữ cảnh này.
-
Không trích dẫn tên ngôn ngữ
ngay cả khi điều đó được chấp nhận (hiện tại). Đó là một số nhận dạng.'plpgsql' -
Bạn có thể gán một biến tại thời điểm khai báo. Tiết kiệm thêm một bước.
-
Các tham số được đặt tên trong tiêu đề. Bỏ những dòng vô nghĩa:
starts_with ALIAS FOR $1; ends_with ALIAS FOR $2;