2012-05-17 38 views
11

Tôi cần tạo một hàm sẽ chạy truy vấn và trả về kết quả với tên bảng và tên cột là các hàm được gán cho hàm. Tôi hiện có:Chức năng truy vấn động Postgres

CREATE OR REPLACE FUNCTION qa_scf(tname character varying, cname character varying) 
RETURNS SETOF INT AS 
$BODY$ 
BEGIN 
RETURN QUERY SELECT * FROM tname WHERE cname !='AK' AND cname!='CK'; 
END; 
$BODY$ 
LANGUAGE plpgsql VOLATILE 
COST 100 
ROWS 1000; 

Điều này cho tôi lỗi "Relation 'tname' không tồn tại" khi chạy. Tôi mới tạo chức năng cho Postgres, vì vậy mọi trợ giúp đều được đánh giá cao. Tôi cảm thấy như int trở lại là sai, nhưng tôi không biết những gì khác để đặt để làm cho nó trả về tất cả các cột cho các hàng trả về. Cảm ơn!

Trả lời

17

Bạn không thể sử dụng biến số thay cho số nhận dạng như vậy. Bạn cần phải làm điều đó với các truy vấn động. Nó sẽ giống như thế này:

EXECUTE 'SELECT * FROM ' || quote_ident(tname) 
     || ' WHERE ' || quote_ident(cname) || ' NOT IN (''AK'',''CK'');' 
INTO result_var; 

Nếu bạn đang sử dụng PostgreSQL 9.1 trở lên, bạn có thể sử dụng the format() function mà làm cho xây dựng chuỗi này dễ dàng hơn nhiều.

+0

Tôi nên khai báo kết quả là gì? –

+1

Không bao giờ nội suy các giá trị vào các câu lệnh sql động mà không sử dụng hàm quote_FOO() thích hợp hoặc bạn mở cửa cho các cuộc tấn công tiêm. – dbenhur

+0

Đây là cơ sở dữ liệu nội bộ. –

13

Không thể chỉ định tên bảng và cột làm tham số hoặc biến mà không xây dựng chuỗi động để thực thi dưới dạng câu lệnh động. Postgres có tài liệu giới thiệu tuyệt vời về executing dynamic statements. Điều quan trọng là trích dẫn đúng số nhận dạng và chữ cái với quote_ident() hoặc quote_literal(). Chức năng format() giúp dọn dẹp cấu trúc câu lệnh sql động. Vì bạn khai báo hàm để trả về SETOF INTEGER, bạn nên chọn trường số nguyên bạn muốn, không phải là *.

CREATE OR REPLACE FUNCTION qa_scf(tname text, cname text) 
RETURNS SETOF INTEGER AS 
$BODY$ 
BEGIN 
    RETURN QUERY EXECUTE format(
    'SELECT the_integer_field FROM %I WHERE %I NOT IN (%L, %L)', 
            tname, cname, 'AK', 'CK' 
); 
END; 
$BODY$ 
LANGUAGE plpgsql; 
+0

Làm cách nào để tôi trả lại tất cả các cột? –

+0

Bạn có thể 'SELECT *' và khai báo 'RETURNS SETOF RECORD'. Sau đó, người tiêu dùng phải hiểu tuple hồ sơ. http://wiki.postgresql.org/wiki/Return_more_than_one_row_of_data_from_PL/pgSQL_functions – dbenhur

+0

Và làm cách nào để cung cấp cho nó danh sách định nghĩa cột? Có cách nào để tự động kéo điều này? –

Các vấn đề liên quan