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

Tên bảng dưới dạng tham số hàm PostgreSQL

Điều này có thể được đơn giản hóa và cải thiện hơn nữa:

CREATE OR REPLACE FUNCTION some_f(_tbl regclass, OUT result integer)
    LANGUAGE plpgsql AS
$func$
BEGIN
   EXECUTE format('SELECT (EXISTS (SELECT FROM %s WHERE id = 1))::int', _tbl)
   INTO result;
END
$func$;

Gọi bằng tên đủ điều kiện giản đồ (xem bên dưới):

SELECT some_f('myschema.mytable');  -- would fail with quote_ident()

Hoặc:

SELECT some_f('"my very uncommon table name"');

Những điểm chính

Sử dụng OUT tham số để đơn giản hóa chức năng. Bạn có thể chọn trực tiếp kết quả của SQL động vào nó và được thực hiện. Không cần các biến và mã bổ sung.

EXISTS làm chính xác những gì bạn muốn. Bạn nhận được true nếu hàng tồn tại hoặc false nếu không thì. Có nhiều cách khác nhau để thực hiện việc này, EXISTS thường hiệu quả nhất.

Có vẻ như bạn muốn một số nguyên quay lại, vì vậy tôi truyền boolean kết quả từ EXISTS thành integer , mang lại chính xác những gì bạn đã có. Tôi sẽ trả lại boolean thay vào đó.

Tôi sử dụng loại mã định danh đối tượng regclass làm kiểu đầu vào cho _tbl . Điều đó thực hiện mọi thứ quote_ident(_tbl) hoặc định dạng format('%I', _tbl) sẽ làm được, nhưng tốt hơn, bởi vì:

  • .. nó ngăn chặn SQL injection cũng như vậy.

  • .. nó không thành công ngay lập tức và duyên dáng hơn nếu tên bảng không hợp lệ / không tồn tại / ẩn đối với người dùng hiện tại. (Một regclass tham số chỉ áp dụng cho hiện tại bảng.)

  • .. nó hoạt động với tên bảng đủ điều kiện giản đồ, trong đó quote_ident(_tbl) đơn giản hoặc định dạng format(%I) sẽ không thành công bởi vì họ không thể giải quyết sự mơ hồ. Bạn sẽ phải chuyển và thoát khỏi tên lược đồ và bảng riêng biệt.

Nó chỉ hoạt động cho hiện có bảng, rõ ràng.

Tôi vẫn sử dụng format() , bởi vì nó đơn giản hóa cú pháp (và để chứng minh cách nó được sử dụng), nhưng với %s thay vì %I . Thông thường, các truy vấn phức tạp hơn nên format() giúp nhiều hơn. Đối với ví dụ đơn giản, chúng ta cũng có thể nối:

EXECUTE 'SELECT (EXISTS (SELECT FROM ' || _tbl || ' WHERE id = 1))::int'

Không cần xác định bảng điều kiện id trong khi chỉ có một bảng duy nhất trong FROM danh sách. Không có sự mơ hồ nào có thể có trong ví dụ này. (Động) Các lệnh SQL bên trong EXECUTE phạm vi riêng biệt , các biến hoặc tham số hàm không hiển thị ở đó - trái ngược với các lệnh SQL thuần túy trong thân hàm.

Đây là lý do tại sao bạn luôn luôn thoát đầu vào của người dùng cho SQL động đúng cách:

db <> fiddle here trình diễn SQL injection
Old sqlfiddle



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách Asind () hoạt động trong PostgreSQL

  2. Sắp xếp chữ và số với PostgreSQL

  3. Số học cột ngày trong truy vấn PostgreSQL

  4. Không tìm thấy trình điều khiển phù hợp khi bao gồm các trình điều khiển cần thiết với maven-assembly-plugin

  5. Dòng lệnh PSQL của Windows:có cách nào cho phép đăng nhập không cần mật khẩu không?