Джино: хостинг и веб-сервисы

Система Orphus
Russian version
Добавить на Del.icio.us
English version
Добавить на Digg.com

 dkLab | Конструктор | PostgreSQL 8.3, 9.1+ эмуляция ALTER ENUM: добавление/удаление элемента, транзакции 

Карта сайта :: Форум «Лаборатории» :: Проект «Денвер»
Проект «Orphus» :: Куроводство: наблы :: Конструктор


2008-08-13

Скачать функции изменения типа ENUM "на лету":
dklab_postgresql_enum_2009-02-26.sql

Как установить

Это просто: скачайте, распакуйте и запустите как обычный SQL-скрипт. В вашей базе данных появится новая схема с именем "enum"; она содержит все необходимые функции.

Постановка проблемы

Хорошо известно, что конструкции ALTER TYPE для удобного типа ENUM PostgreSQL 8.3 отсутствует (а в 9.1 ALTER для ENUM не работает внутри транзакции). Таким образом, вы можете написать:

Листинг 1
CREATE TYPE my_enum AS ENUM('first', 'second');

но после этого — не имеете возможности добавить новый элемент в данный ENUM, если на тип ссылается некоторая таблица. И даже если на какой-то элемент my_enum нет внешних ссылок, вы все равно не можете его удалить стандартными средствами.

В PostgreSQL 9.1+ существует оператор "ALTER TYPE my_enum ADD VALUE 'new_value'", однако он не работает внутри транзакции, что делает его почти бессмысленным в системах миграции. Удаления элемента из ENUM-а также не существует.

Примеры использования: enum_add() и enum_del()

Предлагаемое решение состоит из двух функций, которые позволяют добавлять и удалять элементы в ENUM, производя при этом все необходимые проверки целостности базы данных. Вот несколько примеров их использования.

-- Создаем тип ENUM и ссылающуюся на него таблицу.
CREATE TYPE my_enum AS ENUM('first', 'second');
CREATE TABLE my_table(id INTEGER, my my_enum);

-- Вставляем тестовые данные в таблицу.
INSERT INTO my_table(id, my) VALUES(1, 'second');

-- Добавляем новый элемент в ENUM "на лету".
SELECT enum.enum_add('my_enum', 'third');

-- Удаляем элемент из ENUM "на лету".
SELECT enum.enum_del('my_enum', 'first');
Видите, мы можем удалять элементы из my_enum, если на них отсутствуют ссылки во всех таблицах базы данных. Давайте теперь посмотрим, что произойдет, если мы попробуем удалить элемент 'second', на который ссылается строка таблицы my_table:
-- Удаляем элемент из ENUM "на лету".
SELECT enum.enum_del('my_enum', 'first');
! ERROR: Cannot delete the ENUM element my_enum.second: column public.my_table.my contains references

Итак, целостность базы данных не нарушается, когда мы удаляем элемент из ENUM.

Чайник 

Чтобы добиться максимальной производительности от enum_del() для типа ENUM, вы должны создать во всех таблицах индексы на колонки, ссылающиеся на этот ENUM.







Дмитрий Котеров, Лаборатория dk. ©1999-2016
GZip
Добавить на Del.icio.us   Добавить на Digg.com   Добавить на reddit.com