Điều quan trọng là phải hiểu bản chất chính của năm loại dữ liệu / ký hiệu khác nhau này :
1. 'my_tbl'
Một chuỗi ký tự của unknown
loại . Khi được sử dụng trong SQL (được nhúng trong mã plpgsql hoặc không), nó bị ép buộc thành một loại có nguồn gốc từ ngữ cảnh . Nếu không xác định được kiểu thì có thể yêu cầu diễn viên rõ ràng. Như:'my_tbl'::text
.
2. 'my_tbl'::text
Cùng một chuỗi ký tự được truyền thành nhập text
. Nó có thể chứa tên của một bảng, nhưng nó thực sự chỉ là văn bản.
3. 'my_tbl'::regclass
số nhận dạng đối tượng (OID)
cho một lớp đã đăng ký . Nó được hiển thị và có thể được nhập dưới dạng chuỗi đại diện cho tên đối tượng hợp lệ ('my_tbl'
). Đầu ra tự động đủ điều kiện giản đồ ('my_schema.my_tbl'
) và / hoặc dấu ngoặc kép ('"mY_TbL"'
) nếu nó sẽ không rõ ràng hoặc bất hợp pháp. Nó có thể là một bảng thông thường , trình tự , xem , chế độ xem cụ thể hóa , loại kết hợp vv Chi tiết trong câu trả lời liên quan này:
4. my_tbl_var my_tbl
(viết tắt của my_tbl_var my_tbl%ROWTYPE
)
Trong DECLARE
phần của khối mã plpgsql là phần khai báo biến với nổi tiếng loại hàng
(a.k.a. loại hỗn hợp). Loại phải được đăng ký trong bảng hệ thống pg_class
(giống như với regclass
Biến đổi). Nó không phải là OID của đối tượng được tham chiếu mà là loại hàng thực tế của nó. my_tbl_var
và my_tbl
đều là số nhận dạng ở đây và không thể được tham số hóa. Bạn cũng có thể truyền bất kỳ hàng nào hoặc ghi trực tiếp:(123, 'foo')::my_tbl
5. my_tbl_var record
Trong DECLARE
phần của khối mã plpgsql đó là khai báo của ẩn danh ghi
. Về cơ bản, trình giữ chỗ cho loại hàng chưa xác định / có cấu trúc chưa xác định. Nó có thể được sử dụng trong hầu hết trong số những nơi mà một loại hàng có thể được sử dụng. Nhưng bạn không thể truy cập các trường từ nó trước khi biến bản ghi được chỉ định.
Bạn đã nhầm lẫn 1. , 3. và 4. và đã giải quyết nó bằng cách sử dụng 5. thay vào đó.
Nhưng còn nhiều điều khác nữa sẽ xảy ra tại đây:
-
Bạn đang chọn toàn bộ bảng, nhưng một biến hàng (bản ghi) chỉ có thể giữ một hàng tại một thời điểm. Vì vậy, chỉ cái đầu tiên được gán và trả về. Trong khi không có
ORDER BY
, kết quả là tùy ý và có thể thay đổi bất kỳ lúc nào. Cái bẫy ma quỷ. -
Vì bạn hiện đang sử dụng
record
nhập, bạn cần đảm bảo rằng nó đã được chỉ định trước khi bạn có thể chạy kiểm tra trên các trường của nó, nếu không bạn sẽ nhận được ngoại lệ cho các bảng trống. Trong trường hợp của bạn, hãy kiểm trarecord_var IS NULL
gần như làm cùng một công việc. Nhưng có một trường hợp ở góc đối với các hàng có NULL trong tất cả các trường:sau đórecord_var IS NULL
đánh giá đúng. Thậm chí còn phức tạp hơn đối với bài kiểm traIS NOT NULL
. Thông tin chi tiết tại đây:Tôi đã thêm bản trình diễn vào SQL fiddle bên dưới.
-
Hàm trả về một đại lượng vô hướng (
boolean
) giá trị. Sử dụng:RETURN false;
Thay vì:
RETURN QUERY SELECT false;
Chức năng
CREATE FUNCTION check_valid(_tbl regclass)
RETURNS bool AS
$func$
DECLARE
r record;
_row_ct int;
BEGIN
EXECUTE '
SELECT is_valid, hit_count, hit_limit
FROM ' || _tbl || '
ORDER <whatever>
LIMIT 1' -- replace <whatever> with your sort criteria
INTO r; -- only needed columns
GET DIAGNOSTICS _row_ct = ROW_COUNT;
IF _row_ct = 0 THEN -- necessary, because r may not be assigned
RETURN false;
ELSIF NOT r.is_valid OR r.hit_count > r.hit_limit THEN
RETURN false;
END IF;
RETURN true;
END
$func$ LANGUAGE plpgsql;
SQL Fiddle (với hai biến thể của hàm và bản trình diễn cho hàng IS NULL).
Những điểm chính
-
Sử dụng
GET DIAGNOSTICS
để tìm xem có hàng nào được tìm thấy trong một câu lệnh động hay không vớiEXECUTE
. -
IF
biểu thức có thể được đơn giản hóa. -
Tham số thuộc loại
regclass
, không chỉ là một tên bảng. Tôi sẽ không sử dụng tên gây hiểu lầm "tên bảng" cho tham số này. Điều đó chỉ làm tăng thêm sự bối rối ban đầu của bạn. Gọi nó là_tbl
thay vào đó.
Nếu bạn cũng muốn quay lại một tập hợp các loại hàng biến: