преобразовать тип данных MySQL SET в Postgres - PullRequest
2 голосов
/ 08 декабря 2011

Я пытаюсь преобразовать базу данных MySQL в Postgres. Это расстраивает, но идет неуклонно. Одна проблема, которая поставила меня в тупик, - преобразовать тип данных MySQL SET в Postgres. Тип данных SET в MySQL отличается от простого типа ENUM и не может быть эмулирован с ограничением CHECK.

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

CREATE TABLE foo (color SET('red','green','blue'));

допустит любое из следующих значений в качестве допустимых значений

''
'red'
'red,blue'
'green,red'

и так далее. Близкое приближение в Postgres

CREATE TABLE foo (
    color VARCHAR(10) NOT NULL, 
    CHECK (color IN ('red','green','blue'))
);

, но приведенное выше не допускает «красный, синий» или «зеленый, красный» и т. Д.

Конечно, вышеизложенное является лишь упрощением. Фактическая база данных довольно сложна, с полдюжины столбцов, определенных как SET.

Предложения

1 Ответ

8 голосов
/ 08 декабря 2011

Вы можете использовать массив для столбца, и "содержится в операторе" для ограничения CHECK:

create table pancakes (
    color varchar(10)[] not null,
    check (color <@ ARRAY['red', 'green', 'blue']::varchar[])
);

А потом происходят такие вещи:

=> insert into pancakes values (ARRAY['red']);
INSERT 0 1
=> insert into pancakes values (ARRAY['red','green','blue']);
INSERT 0 1
=> insert into pancakes values (ARRAY['red','green','blue','black']);
ERROR:  new row for relation "pancakes" violates check constraint "pancakes_color_check"
=> select * from pancakes;
      color       
------------------
 {red}
 {red,green,blue}
(2 rows)

Это позволит {red,red} в столбце; если важно запретить {red,red}, вы можете добавить функцию для проверки уникальных значений цвета в массиве и настроить ограничение CHECK:

create function has_unique_colors(varchar[]) returns boolean as $$
    select (select count(distinct c) from unnest($1) as dt(c)) = array_length($1, 1);
$$ language sql;

create table pancakes (
    color varchar(10)[] not null,
    check (color <@ ARRAY['red', 'green', 'blue']::varchar[] and has_unique_colors(color))
);

Другим вариантом будет набор таблиц ассоциаций с простыми скалярными значениями в столбцах. Тем не менее, это может быть громоздким, если у вас есть шесть из этих столбцов. Вы также можете использовать версию функции Эрвина, если вам нужно беспокоиться о NULL в «множествах»:

create function has_unique_colors(varchar[]) returns boolean as $$
    select not exists(select c from unnest($1) dt(c) group by 1 having count(*) > 1);
$$ language sql;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...