5.3. Генерируемые столбцы #

Генерируемый столбец является столбцом особого рода, который всегда вычисляется из других. Таким образом, для столбцов он является тем же, чем представление для таблицы. Есть два типа генерируемых столбцов: сохранённые и виртуальные. Сохранённый генерируемый столбец вычисляется при записи (добавлении или изменении) и занимает место в таблице так же, как и обычный столбец. Виртуальный генерируемый столбец не занимает места и вычисляется при чтении. Поэтому можно сказать, что виртуальный генерируемый столбец похож на представление, а сохранённый генерируемый столбец — на материализованное представление (за исключением того, что он всегда обновляется автоматически). В настоящее время в PostgreSQL реализованы только сохранённые генерируемые столбцы.

Чтобы создать генерируемый столбец, воспользуйтесь предложением GENERATED ALWAYS AS команды CREATE TABLE, например:

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

Ключевое слово STORED, определяющее тип хранения генерируемого столбца, является обязательным. За подробностями обратитесь к CREATE TABLE.

Произвести запись непосредственно в генерируемый столбец нельзя. Поэтому в командах INSERT или UPDATE нельзя задать значение для таких столбцов, хотя ключевое слово DEFAULT указать можно.

Примите к сведению следующие отличия генерируемых столбцов от столбцов со значением по умолчанию. Значение столбца по умолчанию вычисляется один раз, когда в таблицу впервые вставляется строка и никакое другое значение не задано; значение же генерируемого столбца может меняться при изменении строки и не может быть переопределено. Выражение значения по умолчанию не может обращаться к другим столбцам таблицы, а генерирующее выражение, напротив, обычно обращается к ним. В выражении значения по умолчанию могут вызываться изменчивые функции, например, random() или функции, зависящие от времени, а для генерируемых столбцов это не допускается.

С определением генерируемых столбцов и их содержащими таблицами связан ряд ограничений и особенностей:

  • В генерирующем выражении могут использоваться только постоянные функции и не могут фигурировать подзапросы или ссылки на какие-либо значения, не относящиеся к данной строке.

  • Генерирующее выражение не может обращаться к другому генерируемому столбцу.

  • Генерирующее выражение не может обращаться к системным столбцам, за исключением tableoid.

  • Для генерируемого столбца нельзя задать значение по умолчанию или свойство идентификации.

  • Генерируемый столбец не может быть частью ключа секционирования.

  • Генерируемые столбцы могут содержаться в сторонних таблицах. За подробностями обратитесь к CREATE FOREIGN TABLE.

  • Применительно к наследованию и секционированию:

    • Если родительский столбец является генерируемым, его дочерний столбец также должен быть генерируемым; однако дочерний столбец может генерироваться другим выражением. Генерирующее выражение, которое фактически применяется во время вставки или изменения строки, связано с таблицей, в которой физически находится строка. (Это отличается от поведения столбцов со значением по умолчанию: для них применяется значение по умолчанию, которое связано с таблицей, указанной в запросе.)

    • Если родительский столбец не является генерируемым, его дочерний столбец также должен быть негенерируемым.

    • Для унаследованных таблиц, если в определении дочернего столбца нет предложения GENERATED в CREATE TABLE ... INHERITS, то предложение GENERATED будет автоматически копироваться из родительского столбца. Для команды ALTER TABLE ... INHERIT требуется, чтобы родительский и дочерний столбцы уже совпадали в отношении состояния генерации, но не требуется совпадения их генерирующих выражений.

    • Аналогично для секционированных таблиц, если в определении дочернего столбца нет предложения GENERATED в CREATE TABLE ... INHERITS, то его предложение GENERATED будет автоматически копироваться у родительского столбца. Для команды ALTER TABLE ... ATTACH PARTITION требуется, чтобы родительский и дочерний столбцы уже совпадали в отношении состояния генерации, но не требует совпадения их генерирующих выражений.

    • В случае множественного наследования, если один родительский столбец является генерируемым, все соответствующие ему столбцы в иерархии наследования также должны быть генерируемыми. Если генерирующее выражение не одинаковое для всех столбцов, то желаемое выражение для дочернего столбца должно быть указано явно.

Дополнительные замечания касаются использования генерируемых столбцов.

  • Права доступа к генерируемым столбцам существуют отдельно от прав для нижележащих базовых столбцов. Поэтому их можно организовать так, чтобы определённый пользователь мог прочитать генерируемый столбец, но не нижележащие базовые столбцы.

  • Генерируемые столбцы, в соответствии с концепцией, пересчитываются после выполнения триггеров BEFORE. Вследствие этого, в генерируемых столбцах будут отражаться изменения, производимые триггером BEFORE в базовых столбцах, а обращаться в коде такого триггера к генерируемым столбцам, напротив, нельзя.