Статья основана на пятнадцатом видео видео из 31 темы курса SQL 2.0 — PL/pgSQL в PostgreSQL от Аристова Евгения, который является логическим продолжением курса SQL c 0. Ссылки на видео на платформах RUTUBE и VK video.
В данной статье подробно разбираются кортежи, их преимущества и недостатки и когда лучше использовать ROWTYPE.
В прошлой статье мы разобрали входные и выходные параметры, объявление параметров функции и нюанс возвращения функции.
Презентация и исходники доступны по ссылке.
Кортежи
ROWTYPE в PostgreSQL позволяет работать со строками таблиц и составными типами как с едиными объектами.
DECLARE
emp_record employees%ROWTYPE; -- Объявление переменной типа строки таблицы
Преимущества
Автоматическая адаптация к схеме:
При изменении таблицы не нужно менять код функций
ALTER TABLE employees ADD COLUMN email TEXT;
Функция продолжит работать без изменений!
Переменная emp_record автоматически включает новое поле
Удобство работы с целыми строками:
DECLARE
original_emp employees%ROWTYPE;
Модифицируем нужные поля
original_emp.name := new_name;
original_emp.id := DEFAULT;
INSERT INTO employees VALUES (original_emp.*) RETURNING id INTO new_emp_id;
RETURN new_emp_id;
Сравнение целых строк:
current_emp employees%ROWTYPE;
cached_emp employees%ROWTYPE;
Текущее состояние
SELECT * INTO current_emp FROM employees WHERE id = emp_id;
Предположим, что у нас есть кэш (например, в другой таблице)
SELECT * INTO cached_emp FROM employees_cache WHERE id = emp_id;
Сравниваем всю строку целиком
IF current_emp IS DISTINCT FROM cached_emp THEN …
Недостатки
Производительность при частичном использовании:
НЕЭФФЕКТИВНО: выбираем все поля, но используем только одно
CREATE OR REPLACE FUNCTION get_employee_name(emp_id INTEGER)
RETURNS TEXT AS $$
DECLARE
emp employees%ROWTYPE; -- Выбираем ВСЕ поля
BEGIN
SELECT * INTO emp FROM employees WHERE id = emp_id;
RETURN emp.name; -- Используем только одно поле!
END;
$$ LANGUAGE plpgsql;
Отсутствие строгой типизации при изменениях:
Проблема: если удалить поле из таблицы
ALTER TABLE employees DROP COLUMN salary;
Функция сломается в RUNTIME, а не при компиляции
Ошибка: column «salary» of relation «employees» does not exist
Сложность с NULL значениями:
DECLARE
emp employees%ROWTYPE;
BEGIN
-- Инициализация всей строки как
emp := NULL;
-- Попытка доступа к полю вызовет ERROR
-- RAISE NOTICE 'Name: %', emp.name; -- ОШИБКА!
Лучшие практики
Используйте ROWTYPE для:
- Триггерных функций (NEW/OLD)
- Операций со всей строкой
- Прототипирования
Избегайте ROWTYPE для:
- Функций, использующих 1-2 поля
- High-performance кода
- Часто изменяемых таблиц
Больше примеров доступно на гитхабе и в видео.
В следующей статье мы разберём перегрузку функций.
Добавить комментарий