Составные типы данных и вычисляемые поля

Статья основана на двенадцатом видео из 31 темы курса SQL 2.0 — PL/pgSQL в PostgreSQL от Аристова Евгения, который является логическим продолжением курса SQL c 0. Ссылки на видео на платформах RUTUBE и VK видео.

В данной статье подробно разбираются составные типы данных и их ограничения, вычисляемые поля и их минусы.

В прошлой статье мы разобрали категории изменчивости функции, такие как IMMUTABLE, STABLE и VOLATILE.

Презентация и исходники доступны по ссылке.

Составные типы данных

Несмотря на то, что базовых типов 300+, довольно часто необходимо создавать свои типы данных — чем то похоже на объекты и наследование как в ООП.

Например создадим тип валюта:

CREATE TYPE currency AS (
  amount numeric,
  code text
);

И используем его уже в другой таблице с транзакциями:

CREATE TABLE transactions(
  account_id integer,
  debit currency,
  credit currency,
  date_entered date DEFAULT current_date
);

Добавление данных при использовании составных типов

Значения составного типа можно формировать в трёх вариантах:

либо в виде строки, внутри которой в скобках перечислены значения

INSERT INTO transactions VALUES(1, NULL, '(7000.00,"RUR")');

либо с помощью табличного конструктора ROW:

INSERT INTO transactions VALUES(2, ROW(350.00,'RUR'), NULL);

если составной тип содержит более одного поля, то слово ROW можно опустить:

INSERT INTO transactions VALUES(3, (20.00,'RUR'), NULL);
SELECT * FROM transactions;

Доступ ко вложенным объектам осуществляется как обычно — через точку:

CREATE FUNCTION multiply(factor numeric, cur currency) RETURNS currency AS $$
  SELECT ROW(factor * cur.amount, cur.code)::currency;
$$ IMMUTABLE LANGUAGE SQL;
SELECT account_id, multiply(2,debit), multiply(2,credit), date_entered FROM transactions;

Ограничения

  • добавлять/удалять поля через alter type add/remove field, что может накладывать ограничения на модификацию существующих данных
  • Ограниченная поддержка индексов
  • Сложности с миграциями
  • Не все клиентские библиотеки хорошо поддерживают

Составные типы отлично подходят для сложных структур данных, где нужна строгая типизация и логическая группировка полей!

Виртуальные колонки

С недавних пор у нас появилась возможность создавать и использовать генерируемые колонки — GENERATED ALWAYS. Кроме дополнительных вычислений минусом является необходимость их хранить рядом с данными.

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

Например Фамилия И.О. на основании ФИО.

Так бы нам пришлось каждый раз повторять формулу — а в данном случае мы просто указываем имя дополнительного поля по имени функции:

CREATE FUNCTION textcurrency(cur currency) RETURNS text AS $$
  SELECT cur.amount || cur.code;
$$ IMMUTABLE LANGUAGE SQL;

SELECT t.*, textcurrency(t.debit) as debit, textcurrency(t.credit) as credit FROM transactions t;

Усложним ситуацию, и передадим внутрь функции всю строку таблицы:

CREATE FUNCTION textcurrency(tr transactions) RETURNS text AS $$

    SELECT tr.account_id || tr.date_entered::text;

$$ IMMUTABLE LANGUAGE SQL;

SELECT t.*, textcurrency(t.*) FROM transactions t;

Синтаксисом допускается обращение к функции как к столбцу таблицы без явного указания (и наоборот, к столбцу как к функции).

SELECT t.*, t.textcurrency FROM transactions t;

И получили полную виртуальную колонку — вычисляется каждый раз при вызове функции!

Почему 2 функции имеют одинаковое имя и при этом работают одновременно, мы разберём в 16 теме.

Виртуальные колонки. Минусы

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

Больше примеров доступно на гитхабе и в видео.

В следующей статье мы разберём использование операторов.


Опубликовано

в

Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

двенадцать + 4 =