Các cột được tính toán / tính toán / ảo / dẫn xuất trong PostgreSQL


113

PostgreSQL có hỗ trợ các cột được tính toán / tính toán, như MS SQL Server không? Tôi không thể tìm thấy bất kỳ thứ gì trong tài liệu, nhưng vì tính năng này được bao gồm trong nhiều DBMS khác nên tôi nghĩ rằng tôi có thể thiếu một thứ gì đó.

Ví dụ: http://msdn.microsoft.com/en-us/library/ms191250.aspx


Sử dụng biểu thức truy vấn con bên (tính năng Postgres), bạn có thể dễ dàng thêm nhiều cột hơn vào mỗi hàng.
Victor

Câu trả lời:


139

Lên đến Postgres 11 cột được tạo không được hỗ trợ - như được định nghĩa trong tiêu chuẩn SQL và được thực hiện bởi một số RDBMS bao gồm DB2, MySQL và Oracle. Cũng không phải "cột được tính toán" tương tự của SQL Server.

STOREDcác cột được tạo được giới thiệu với Postgres 12 . Ví dụ tầm thường:

CREATE TABLE tbl (
  int1    int
, int2    int
, product bigint GENERATED ALWAYS AS (int1 * int2) STORED
);

db <> fiddle here

VIRTUALcác cột được tạo có thể đi kèm với một trong các lần lặp tiếp theo. (Chưa có trong Postgres 13).

Có liên quan:


Cho đến lúc đó , bạn có thể mô phỏng VIRTUALcác cột đã tạo bằng một hàm sử dụng ký hiệu thuộc tính ( tbl.col) trông và hoạt động giống như một cột được tạo ảo . Đó là một chút kỳ lạ về cú pháp tồn tại trong Postgres vì ​​những lý do lịch sử và tình cờ phù hợp với trường hợp. Câu trả lời liên quan này có các ví dụ về mã :

Tuy nhiên, biểu thức (trông giống như một cột) không được bao gồm trong a SELECT * FROM tbl. Bạn luôn phải liệt kê nó một cách rõ ràng.

Cũng có thể được hỗ trợ với một chỉ mục biểu thức phù hợp - với điều kiện là hàm IMMUTABLE. Giống:

CREATE FUNCTION col(tbl) ... AS ...  -- your computed expression here
CREATE INDEX ON tbl(col(tbl));

Giải pháp thay thế

Ngoài ra, bạn có thể triển khai chức năng tương tự với a VIEW, được kết hợp tùy chọn với các chỉ mục biểu thức. Sau đó, SELECT *có thể bao gồm cột đã tạo.

Các STOREDcột được tính toán "Persisted" ( ) có thể được triển khai với trình kích hoạt theo cách giống hệt nhau về mặt chức năng.

Các quan điểm vật chất hóa là một khái niệm có liên quan chặt chẽ, được triển khai kể từ Postgres 9.3 .
Trong các phiên bản trước, người ta có thể quản lý các MV theo cách thủ công.


Tùy thuộc vào lượng dữ liệu bạn đang tải cùng lúc .. trình kích hoạt có thể làm mọi thứ chậm lại đáng kể. Có thể muốn xem xét các bản cập nhật thay thế.
sam yi

1
Các giải pháp này khá vô dụng (không có sự thay đổi mã lớn đối với một cơ sở mã không có trường hợp thử nghiệm) khi chuyển từ oracle sang postgres. Có giải pháp nào từ khía cạnh di cư không?
happybuddha

@happybuddha: Vui lòng đặt câu hỏi của bạn dưới dạng câu hỏi. Nhận xét không phải là nơi. Bạn luôn có thể liên kết đến câu hỏi này để biết ngữ cảnh (và thêm nhận xét ở đây để thu hút sự chú ý của tôi và liên kết đến câu hỏi liên quan).
Erwin Brandstetter

4
Chức năng đang được phát triển ngay bây giờ: commitfest.postgresql.org/16/1443
r90t

1
@cryanbhu: Phụ thuộc vào chi tiết thiết lập và yêu cầu của bạn. Bạn có thể hỏi một câu hỏi mới với thông tin cần thiết.
Erwin Brandstetter

32

CÓ bạn có thể !! Giải pháp phải dễ dàng, an toàn và hiệu quả ...

Tôi mới sử dụng postgresql, nhưng có vẻ như bạn có thể tạo các cột được tính toán bằng cách sử dụng chỉ mục biểu thức , được ghép nối với một chế độ xem (chế độ xem là tùy chọn, nhưng làm cho cuộc sống dễ dàng hơn một chút).

Giả sử tính toán của tôi là md5(some_string_field), sau đó tôi tạo chỉ mục là:

CREATE INDEX some_string_field_md5_index ON some_table(MD5(some_string_field));

Bây giờ, bất kỳ truy vấn nào hoạt động MD5(some_string_field)sẽ sử dụng chỉ mục thay vì tính toán nó từ đầu. Ví dụ:

SELECT MAX(some_field) FROM some_table GROUP BY MD5(some_string_field);

Bạn có thể kiểm tra điều này với giải thích .

Tuy nhiên tại thời điểm này, bạn đang dựa vào những người sử dụng bảng biết chính xác cách tạo cột. Để làm cho cuộc sống dễ dàng hơn, bạn có thể tạo một VIEWphiên bản tăng cường của bảng gốc, thêm giá trị được tính toán dưới dạng một cột mới:

CREATE VIEW some_table_augmented AS 
   SELECT *, MD5(some_string_field) as some_string_field_md5 from some_table;

Bây giờ bất kỳ truy vấn nào sử dụng some_table_augmentedsẽ có thể sử dụng some_string_field_md5mà không cần lo lắng về cách hoạt động của nó..chúng chỉ có được hiệu suất tốt. Chế độ xem này không sao chép bất kỳ dữ liệu nào từ bảng gốc, vì vậy nó rất tốt về bộ nhớ cũng như hiệu suất. Tuy nhiên, lưu ý rằng bạn không thể cập nhật / chèn vào một dạng xem, chỉ vào bảng nguồn, nhưng nếu bạn thực sự muốn, tôi tin rằng bạn có thể chuyển hướng các lần chèn và cập nhật đến bảng nguồn bằng cách sử dụng các quy tắc (Tôi có thể sai ở điểm cuối cùng như Tôi chưa bao giờ tự mình thử).

Chỉnh sửa: có vẻ như nếu truy vấn liên quan đến các chỉ số cạnh tranh, công cụ lập kế hoạch đôi khi có thể không sử dụng biểu thức-chỉ mục nào cả. Sự lựa chọn dường như phụ thuộc vào dữ liệu.


1
Bạn có thể vui lòng giải thích hoặc cho một ví dụ về if the query involves competing indices?
dvtan

17

Một cách để làm điều này là sử dụng một bộ kích hoạt!

CREATE TABLE computed(
    one SERIAL,
    two INT NOT NULL
);

CREATE OR REPLACE FUNCTION computed_two_trg()
RETURNS trigger
LANGUAGE plpgsql
SECURITY DEFINER
AS $BODY$
BEGIN
    NEW.two = NEW.one * 2;

    RETURN NEW;
END
$BODY$;

CREATE TRIGGER computed_500
BEFORE INSERT OR UPDATE
ON computed
FOR EACH ROW
EXECUTE PROCEDURE computed_two_trg();

Trình kích hoạt được kích hoạt trước khi hàng được cập nhật hoặc chèn. Nó thay đổi trường mà chúng ta muốn tính toán NEWbản ghi và sau đó nó trả về bản ghi đó.


Khi nào thì bộ kích hoạt phát nổ? Tôi chạy ở trên và đã làm điều này insert into computed values(1, 2); insert into computed values(4, 8); commit; select * from computed;và nó chỉ trả về: 1 2 và 4 8
happybuddha

2
hãy thử insert into computed(one) values(1); insert into computed(one) values(4); commit; select * from computed;giá trị của twocột sẽ được tính toán tự động!
Elmer

8

PostgreSQL 12 hỗ trợ các cột được tạo:

PostgreSQL 12 Beta 1 đã được phát hành!

Các cột đã tạo

PostgreSQL 12 cho phép tạo các cột được tạo để tính toán các giá trị của chúng với một biểu thức sử dụng nội dung của các cột khác. Tính năng này cung cấp các cột được tạo được lưu trữ, được tính toán trên các bản chèn và bản cập nhật và được lưu trên đĩa. Các cột được tạo ảo, chỉ được tính khi một cột được đọc như một phần của truy vấn, chưa được triển khai.


Các cột đã tạo

Cột được tạo là một cột đặc biệt luôn được tính toán từ các cột khác. Do đó, đối với các cột, chế độ xem đối với bảng là gì.

CREATE TABLE people (
    ...,
    height_cm numeric,
    height_in numeric GENERATED ALWAYS AS (height_cm * 2.54) STORED
);

db <> bản trình diễn fiddle



1

Chà, không chắc đây có phải ý bạn không nhưng Posgres thường hỗ trợ cú pháp ETL "dummy". Tôi đã tạo một cột trống trong bảng và sau đó cần điền vào nó bằng các bản ghi được tính toán tùy thuộc vào các giá trị trong hàng.

UPDATE table01
SET column03 = column01*column02; /*e.g. for multiplication of 2 values*/
  1. Nó quá giả Tôi nghi ngờ nó không phải là những gì Bạn đang tìm kiếm.
  2. Rõ ràng là nó không động, bạn chạy nó một lần. Nhưng không có trở ngại nào để đưa nó vào kích hoạt.

0

Tôi có một mã hoạt động và sử dụng thuật ngữ được tính toán, tôi không sử dụng postgresSQL thuần túy vì chúng tôi chạy trên PADB

đây là cách nó được sử dụng

create table some_table as
    select  category, 
            txn_type,
            indiv_id, 
            accum_trip_flag,
            max(first_true_origin) as true_origin,
            max(first_true_dest ) as true_destination,
            max(id) as id,
            count(id) as tkts_cnt,
            (case when calculated tkts_cnt=1 then 1 else 0 end) as one_way
    from some_rando_table
    group by 1,2,3,4    ;

PADB chính xác là gì?
Gherman

Cơ sở dữ liệu phân tích ParAccel nó cũ nhưng đẹp ... en.wikipedia.org/wiki/ParAccel
Wired604

Nhưng nó liên quan như thế nào đến một câu hỏi về Postgres? Chắc chắn có rất nhiều DB có hỗ trợ các cột được tính toán.
Gherman

ah xin lỗi tôi đã không dành thời gian để quay lại ngữ cảnh .... PADB dựa trên hậu quả!
Wired604

-6

Một giải pháp nhẹ với ràng buộc Kiểm tra:

CREATE TABLE example (
    discriminator INTEGER DEFAULT 0 NOT NULL CHECK (discriminator = 0)
);

6
Điều này có liên quan như thế nào đến khái niệm cột được tính toán? Bạn có quan tâm để giải thích?
Erwin Brandstetter

4
Đồng ý, nó không liên quan trực tiếp. Nhưng là một sự thay thế cho một trường hợp đơn giản khi bạn chỉ cần làm những việc tương tự field as 1 persisted.
cinereo

2
Một mô tả thực sự sẽ được tốt đẹp. Tôi nghĩ câu trả lời này là nếu việc tính toán có thể được thực hiện với mệnh đề mặc định thì bạn có thể sử dụng ràng buộc kiểm tra và mặc định để ngăn bất kỳ ai thay đổi giá trị.
Ross Bradbury

@Ross Bradbury: Đồng ý, nhưng điều đó chỉ hoạt động với chèn. Nó sẽ không hoạt động nếu một cột phụ thuộc được cập nhật.
Stefan Steiger
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.