PostgreSQL: Генеровані стовпці


16

Чи підтримує PostgreSQL створені стовпці ? Також відомі як віртуальні стовпці . Я не кажу про IDENTITYколонки .

Я не можу знайти жодної інформації про цю чудову функцію, але я знаю, що вона доступна на SQL Server та в останніх версіях MariaDB & MySQL.

Ця функція згадується в стандарті SQL: 2003 , і на форумах PostgreSQL було близько дискусії близько 2006 року, але я не можу знайти нічого істотного в цьому питанні.

Існує певна дискусія щодо SO, але вона вже досить стара, тому вона, можливо, застаріла.


2
Ця відповідна відповідь від 2012 року щодо ПЗ може бути корисною : stackoverflow.com/questions/11165450/… Досі діє.
Erwin Brandstetter

@ErwinBrandstetter Вибачте, що я пропустив цей коментар. Це корисна хитрість. Спасибі.
Манго

Відповіді:


17

Не впевнений, що це те, що ви хочете, але позначення атрибутів row.full_nameі позначення функції full_name(row)еквівалентні в postgresql.

Це означає, що ви берете стіл

CREATE TABLE people (
  first_name text,
  last_name text
);

і функція:

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

і називайте це так:

select full_name from people

Це те, що вам потрібно?

Щоб пришвидшити речі, ви можете створити індекс вираження:

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

Або зберігати все в матеріалізованому вигляді.

Приклад взятий звідси: http://bernardoamc.github.io/sql/2015/05/11/postgres-virtual-column/


2
Це правильна відповідь. Дивіться, наприклад, як Postgrest ставиться до такої поведінки як "обчислені стовпці".
fiatjaf

Опечатка, я думаю - вибір повинен бути select people.full_name from peopleчи select full_name(people) from people?
Баргуаст

Ні, це не працює так. Префікс у "select people.full_name from people" може бути залишений, як у звичайному SQL.
Fabian Zeindl

Я пропустив цю відповідь, прийшов, як би довго, після того, як я здався. Дякую за пропозицію.
Манго

1
Чи можете ви змінити прийняту відповідь тоді?
Фабіан Зейндл

6

Ні, це наразі (на Postgres 9.6) не підтримується.

Єдине вирішення - використовувати тригер або представлення, якщо це простий розрахунок, який вам не потрібно індексувати.


Щури Я гадаю, що я міг би поглянути на матеріалізований погляд, якщо мені буде потрібна вистава. Я додав запит на цю функцію, оскільки вона вже доступна в конкурсі.
Манго

1
Не потрібно MVIEW. Стовпець із тригером також дозволить проіндексувати вміст стовпця
a_horse_with_no_name

У мене є філософська проблема зі збереженням додаткових реальних стовпців, які в основному є повторенням інших даних. Це знеструмлює таблицю.
Манго

5
Що ж, обчислений стовпець саме такий: зберігання денормованих даних. Як генерується значення обчисленої колонки, значення не має. Я не бачу концептуальної різниці між "реальним" обчисленим стовпцем та тим, що генерується через тригер
a_horse_with_no_name

Інше вирішення (у деяких випадках) - індексувати вираз.
ypercubeᵀᴹ

5

Так: GENERATED ALWAYS AS … STORED

Postgres 12 додає функціональність для згенерованих стовпців, як згадується у стандарті SQL: 2003 .

Значення генерується під час INSERTабо UPDATE, а потім зберігається з рядком, як і будь-яке інше значення.

Створений повинен базуватися на базовому стовпчику тієї ж таблиці або на незмінній функції .

Синтаксис простий, пункт про CREATE TABLE:

GENERATED ALWAYS AS ( generation_expr ) STORED 

Приклад:

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

Особливості:

  • Можна індексувати.
  • Частина стандарту SQL.

Застереження:

  • На основі стовпців тієї ж таблиці (не пов'язаних з ними таблиць)
  • Не дозволено для розділення (не може бути частиною ключа розділу)
  • Дані завжди записуються в рядки, займаючи місця для зберігання
    • Майбутня функція може запропонувати VIRTUAL для значень, обчислених під час руху без зберігання
  • Одноколінне поглиблення (використовуйте базовий стовпець, а не інший генерований стовпець)
  • НЕ ЗАГАЛЕНО ЗАМОВЛЕННЯ (ви не можете переоцінити значення)
  • Неможливо отримати доступ до gen-col у ПЕРЕШЕК тригера (значення ще не визначено)
  • Функції повинні бути незмінними

Побачити:


Дякую за цю інформацію. Я бачу, що версія 12 ще не повністю випущена, але я з нетерпінням чекаю її. Зауважу, що PostgreSQL використовує більш стандартний синтаксис, але інакше такий же, як MSSQL. Я знайшов специфікацію SQL2003 тут: sigmodrecord.org/publications/sigmodRecord/0403 / ... . Я завжди говорив, що SQL є дуже повільним стандартом, а впровадження СУБД - навіть повільним.
Манго

0

Залежно від використання, ви можете домогтися подібної поведінки, оголосивши новий стовпець і заповнивши його тригером при вставці / оновленні.

Я б використав наведені вище відповіді, якщо це можливо, щоб уникнути дублювання даних, які можуть бути отримані з того, що у вас вже є, але це зробити трюк і може бути корисним для обчислювально інтенсивних похідних полів, які ви хочете обчислити один раз і зберегти.

Я розглядав такий підхід, щоб вирішити питання, коли інколи мав лише 15 цифр 18-значного ключа (останні 3 цифри - це лише контрольна сума), але хотів мати можливість застосувати відносини із зовнішнім ключем.

Документи PG на тригерах: https://www.postgresql.org/docs/9.6/sql-createtrigger.html

Приклад W3: https://www.w3resource.com/PostgreSQL/postgresql-triggers.php

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.