PostgreSQL: Cột được tạo


16

PostgreSQL có hỗ trợ các cột được tạo không? Còn gọi là cột ảo . Tôi không nói về IDENTITYcột .

Tôi không thể tìm thấy bất kỳ thông tin nào về tính năng đáng chú ý này nhưng tôi biết rằng nó có sẵn trên SQL Server và trong các phiên bản mới nhất của MariaDB & MySQL.

Tính năng này được đề cập trong tiêu chuẩn SQL: 2003 và đã có một số cuộc thảo luận trên các diễn đàn PostgreQuery vào khoảng năm 2006, nhưng tôi không thể tìm thấy bất cứ điều gì đáng kể về vấn đề này.

Có một số cuộc thảo luận về SO, nhưng nó đã khá cũ, vì vậy nó có thể đã lỗi thời.


2
Câu trả lời liên quan này từ năm 2012 trên SO có thể hữu ích: stackoverflow.com/questions/11165450/NH Vẫn còn hiệu lực.
Erwin Brandstetter

@ErwinBrandstetter Xin lỗi tôi đã bỏ lỡ nhận xét này. Đó là một mẹo hữu ích. Cảm ơn.
Manngo

Câu trả lời:


17

Không chắc chắn nếu đây là những gì bạn muốn, nhưng ký hiệu thuộc tính row.full_namevà ký hiệu hàm full_name(row)là tương đương trong postgresql.

Điều đó có nghĩa là bạn lấy một cái bàn

CREATE TABLE people (
  first_name text,
  last_name text
);

và một chức năng:

CREATE FUNCTION full_name(people) RETURNS text AS $$
  SELECT $1.first_name || ' ' || $1.last_name;
$$ LANGUAGE SQL;

và gọi nó như thế này:

select full_name from people

Có phải đó là những gì bạn cần?

Để tăng tốc mọi thứ, bạn có thể tạo một chỉ mục biểu thức:

CREATE INDEX people_full_name_idx ON people
USING GIN (to_tsvector('english', full_name(people)));

Hoặc lưu trữ mọi thứ trong một cái nhìn cụ thể hóa.

Ví dụ được lấy từ đây: http://bernardoamc.github.io/sql/2015/05/11/postgres-virtual-columns/


2
Đây là câu trả lời chính xác. Xem, ví dụ, làm thế nào Postgrest đề cập đến hành vi này là "cột tính".
fiatjaf

Typo, tôi nghĩ - lựa chọn nên là select people.full_name from peoplehay select full_name(people) from people?
Barguast

Không, nó hoạt động như thế. Tiền tố trong "select people.full_name từ mọi người" có thể được bỏ qua như trong SQL thông thường.
Fabian Zeindl

Tôi đã bỏ lỡ câu trả lời này, sắp tới, rất lâu sau khi tôi bỏ cuộc. Cám ơn vì sự gợi ý.
Manngo

1
Bạn có thể thay đổi câu trả lời được chấp nhận sau đó?
Fabian Zeindl

6

Không, điều này hiện tại (kể từ Postgres 9.6) không được hỗ trợ.

Cách giải quyết duy nhất là sử dụng trình kích hoạt hoặc chế độ xem nếu đó là một phép tính đơn giản mà bạn không cần lập chỉ mục.


Chuột Tôi cho rằng tôi có thể đi đến một cái nhìn cụ thể hóa nếu tôi cần hiệu suất. Tôi đã thêm một yêu cầu cho tính năng này, vì nó đã có sẵn trong cuộc thi.
Manngo

1
Không cần MVIEW. Một cột có trình kích hoạt cũng sẽ cho phép bạn lập chỉ mục nội dung của cột
a_horse_with_no_name

Tôi có một vấn đề triết học với việc lưu trữ các cột thực bổ sung mà về cơ bản là sự lặp lại của các dữ liệu khác. Nó khử bình thường bảng.
Manngo

5
Vâng, một cột được tính toán chính xác là: lưu trữ dữ liệu không chuẩn hóa. Làm thế nào giá trị của cột được tính toán được tạo ra không quan trọng. Tôi không thấy sự khác biệt về khái niệm giữa một "thực" cột tính và một trong đó được tạo ra thông qua một cò
a_horse_with_no_name

Một cách giải quyết khác (đối với một số trường hợp) là lập chỉ mục một biểu thức.
ypercubeᵀᴹ

5

Đúng: GENERATED ALWAYS AS … STORED

Postgres 12 thêm chức năng cho các cột được tạo, như được đề cập trong tiêu chuẩn SQL: 2003 .

Giá trị được tạo tại thời điểm của một INSERThoặc UPDATE, sau đó được lưu trữ với hàng giống như bất kỳ giá trị nào khác.

Một được tạo phải dựa trên một cột cơ sở của cùng một bảng hoặc trên một hàm bất biến .

Cú pháp rất đơn giản, một mệnh đề về CREATE TABLE:

GENERATED ALWAYS AS ( generation_expr ) STORED 

Thí dụ:

CREATE TABLE people (
    ...,
    height_cm NUMERIC,
    height_in NUMERIC GENERATED ALWAYS AS ( height_cm / 2.54 ) STORED
);

Đặc trưng:

  • Có thể được lập chỉ mục.
  • Một phần của tiêu chuẩn SQL.

Hãy cẩn thận:

  • Dựa trên các cột của cùng một bảng (không liên quan đến bảng)
  • Không được phép phân vùng (không thể là một phần của khóa phân vùng)
  • Dữ liệu luôn được ghi vào hàng, chiếm dung lượng trong bộ lưu trữ
    • Tính năng trong tương lai có thể cung cấp VIRTUAL cho các giá trị được tính khi đang di chuyển mà không cần lưu trữ
  • Sâu thế hệ đơn (sử dụng cột cơ sở, không phải cột khác được tạo)
  • Không có TẠO B BYNG DEFAULT (bạn không thể ghi đè giá trị)
  • Không thể truy cập gen-col trong trình kích hoạt TRƯỚC (giá trị chưa được xác định)
  • Chức năng phải bất biến

Xem:


Cảm ơn thông tin đó. Tôi thấy rằng phiên bản 12 vẫn chưa được phát hành đầy đủ, nhưng tôi đang mong chờ nó. Tôi lưu ý rằng PostgreSQL sử dụng cú pháp chuẩn hơn, nhưng khác với MSSQL. Tôi đã tìm thấy các thông số kỹ thuật SQL2003 ở đây: sigmodrecord.org/publications/sigmodRecord/0403/ . Tôi đã luôn nói rằng SQL là một tiêu chuẩn di chuyển rất chậm và việc triển khai DBMS thậm chí còn chậm.
Manngo

0

Tùy thuộc vào trường hợp sử dụng của bạn, bạn có thể đạt được loại hành vi này bằng cách khai báo một cột mới và điền vào nó bằng một kích hoạt khi chèn / cập nhật.

Tôi sẽ sử dụng các câu trả lời ở trên nếu có thể để tránh trùng lặp dữ liệu có thể là dẫn xuất từ ​​những gì bạn đã có, nhưng nó thực hiện được mẹo và có thể hữu ích cho các trường dẫn xuất chuyên sâu tính toán mà bạn muốn tính toán một lần và lưu lại.

Tôi đã xem xét phương pháp này để giải quyết một vấn đề mà đôi khi tôi chỉ có 15 chữ số của khóa 18 chữ số (3 chữ số cuối chỉ là một tổng kiểm tra) nhưng muốn có thể thực thi mối quan hệ khóa ngoài.

Tài liệu PG về trình kích hoạt: https://www.postgresql.org/docs/9.6/sql-createtrigger.html

Ví dụ về W3: https://www.w3resource.com/PostgreSQL/postgresql-triggers.php

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.