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

Chuyển động tên cột cho một biến bản ghi trong PostgreSQL

Làm việc với bảng giả này

CREATE TEMP TABLE foo (id int, my_num numeric);
INSERT INTO foo VALUES (1, 12.34)

Đầu tiên, tôi đã đơn giản hóa và làm sạch ví dụ của bạn:

  • Đã xóa một số nhiễu không liên quan đến câu hỏi.

  • RETURNS SETOF void hầu như không có ý nghĩa. Tôi sử dụng RETURNS void thay vào đó.

  • Tôi sử dụng text thay vì character varying , chỉ vì mục đích đơn giản.

  • Khi sử dụng SQL động, bạn để bảo vệ khỏi việc đưa vào SQL, tôi sử dụng format() với %I trong trường hợp này. Có nhiều cách khác.

Vấn đề cơ bản là SQL rất cứng nhắc với các kiểu và định danh. Bạn đang thao tác với bảng động tên cũng như với tên trường động của bản ghi - một ẩn danh ghi lại trong ví dụ ban đầu của bạn. Pl / pgSQL không được trang bị tốt để đối phó với điều này. Postgres không biết có gì bên trong một bản ghi ẩn danh. Chỉ sau khi bạn gán bản ghi cho loại nổi tiếng bạn có thể tham khảo các trường riêng lẻ không.
Đây là một câu hỏi có liên quan chặt chẽ, cố gắng đặt một trường của bản ghi có tên động:
Cách đặt giá trị của trường biến tổng hợp bằng cách sử dụng SQL động

Chức năng cơ bản

CREATE OR REPLACE FUNCTION getrowdata1(table_name text, id int)
  RETURNS void AS
$func$ 
DECLARE
   srowdata record;
   reqfield text := 'my_num';   -- assigning at declaration time for convenience
   value    numeric;
BEGIN

RAISE NOTICE 'id: %', id; 

EXECUTE format('SELECT * FROM %I WHERE id = $1', table_name)
USING  id
INTO   srowdata;

RAISE NOTICE 'srowdata: %', srowdata;

RAISE NOTICE 'srowdatadata.my_num: %', srowdata.my_num;

/* This does not work, even with dynamic SQL
EXECUTE format('SELECT ($1).%I', reqfield)
USING srowdata
INTO value;

RAISE NOTICE 'value: %', value;
*/

END
$func$ LANGUAGE plpgsql;

Gọi:

SELECT * from getrowdata1('foo', 1);

Phần được nhận xét sẽ nêu ra một ngoại lệ:

không thể xác định cột "my_num" trong loại dữ liệu bản ghi:SELECT * fromgetrowdata (1, 'foo')

hstore

Bạn cần cài đặt mô-đun bổ sung hstore cho điều này. Mỗi cơ sở dữ liệu một lần với:

CREATE EXTENSION hstore;

Sau đó, tất cả có thể hoạt động như thế này:

CREATE OR REPLACE FUNCTION getrowdata2(table_name text, id int)
  RETURNS void AS
$func$ 
DECLARE
   hstoredata hstore;
   reqfield   text := 'my_num';
   value      numeric;
BEGIN

RAISE NOTICE 'id: %', id; 

EXECUTE format('SELECT hstore(t) FROM %I t WHERE id = $1', table_name)
USING  id
INTO   hstoredata;

RAISE NOTICE 'hstoredata: %', hstoredata;

RAISE NOTICE 'hstoredata.my_num: %', hstoredata -> 'my_num';

value := hstoredata -> reqfield;

RAISE NOTICE 'value: %', value;

END
$func$ LANGUAGE plpgsql;

Gọi:

SELECT * from getrowdata2('foo', 1);

Kiểu đa hình

Thay thế mà không cần cài đặt các mô-đun bổ sung.

Vì bạn chọn toàn bộ hàng vào biến bản ghi của mình, nên có một loại được xác định rõ ràng cho nó theo định nghĩa. Sử dụng nó. Từ khóa là các loại đa hình .

CREATE OR REPLACE FUNCTION getrowdata3(_tbl anyelement, id int)
  RETURNS void AS
$func$ 
DECLARE
   reqfield text := 'my_num';
   value    numeric;
BEGIN

RAISE NOTICE 'id: %', id; 

EXECUTE format('SELECT * FROM %s WHERE id = $1', pg_typeof(_tbl))
USING  id
INTO   _tbl;

RAISE NOTICE '_tbl: %', _tbl;

RAISE NOTICE '_tbl.my_num: %', _tbl.my_num;

EXECUTE 'SELECT ($1).' || reqfield   -- requfield must be SQLi-safe or escape
USING _tbl
INTO  value;

RAISE NOTICE 'value: %', value;

END
$func$ LANGUAGE plpgsql;

Gọi:

SELECT * from getrowdata3(NULL::foo, 1);

-> SQLfiddle

  • Tôi (ab-) sử dụng tham số đầu vào _tbl cho ba mục đích ở đây:

    • Cung cấp loại được xác định rõ ràng của hồ sơ
    • Cung cấp tên của bảng, tự động đủ điều kiện giản đồ
    • Phục vụ như một sự thay đổi.
  • Giải thích thêm trong câu trả lời có liên quan này (chương cuối):
    Refactor một hàm PL / pgSQL để trả về kết quả đầu ra của các truy vấn SELECT khác nhau




  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ó nhóm theo điều khoản - elein’s GeneralBits

  2. datagrip Không thể áp dụng các thay đổi Bảng này chỉ được đọc. Không thể áp dụng các thay đổi của trình chỉnh sửa ô

  3. Vai trò không tồn tại và không thể tạo cơ sở dữ liệu khi sử dụng PostgreSQL

  4. Thay vì LIKE và ~, tại sao chỉ SIMILAR TO hoạt động khi thực hiện kết hợp regex với các lựa chọn thay thế

  5. Các đối tượng lớn có thể không được sử dụng trong chế độ tự động cam kết