PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

plpgsql - sử dụng tên bảng động trong câu lệnh khai báo

Đ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_varmy_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. 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 tra record_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 tra IS 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ới EXECUTE .

  • 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:



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. org.postgresql.util.PSQLException:FATAL:không có mục nhập pg_hba.conf cho máy chủ

  2. Có gì sai với TRƯỜNG HỢP của tôi?

  3. DROP TABLE IF EXISTS Ví dụ trong PostgreSQL

  4. Kiểm tra sự tồn tại của chỉ mục trong PostgreSQL

  5. Trừ các tuần cho một ngày trong PostgreSQL