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
в базовых столбцах, а обращаться в коде такого триггера к генерируемым столбцам, напротив, нельзя.Генерируемые столбцы не участвуют в логической репликации и не могут быть указаны в списке столбцов
CREATE PUBLICATION
.