Могу ли я сравнить перечисления MySQL? - PullRequest
8 голосов
/ 17 ноября 2008

У меня есть перечисление: ENUM( 'alpha', 'beta', 'gamma', 'delta', 'omega' )

Если я сортирую свою таблицу по этому столбцу, я получаю их в правильном порядке, определенном выше.

Однако я не могу найти способ выбрать их подмножество, например все до дельты. Использование WHERE status < 'delta' возвращает только альфа и бета, а не гамму. Похоже, MySQL использует сравнение строк, а не сравнение перечислений.

Я мог бы использовать индексные числа - т.е. WHERE status < 4 - но это немного запах кода (магические числа) и может сломаться, если я добавлю новые значения в перечисление.

Ответы [ 5 ]

7 голосов
/ 17 ноября 2008

Вы пытаетесь использовать методы манипулирования данными с метаданными, и это непросто.

Это хорошая причина для замены ENUM внешним ключом для таблицы поиска. Тогда вы можете использовать обычные методы манипулирования данными.

5 голосов
/ 01 апреля 2011

Вы можете использовать status+0, чтобы вернуть индекс ENUM, начиная с 1.

См. http://serghei.net/docs/database/mysql/doc/E/N/ENUM.html

3 голосов
/ 13 октября 2009

только что столкнулся с той же проблемой. если вы хотите отсортировать поле перечисления, вы должны сначала привести его к строковому типу (категория - это мое поле перечисления в примере):

SELECT
CONVERT(category USING utf8) as str_category 
FROM
example
GROUP BY
str_category
ORDER BY 
str_category

Eazy!

2 голосов
/ 17 ноября 2008

Вы можете использовать FIELD(column, "string1", "string2", ...), чтобы найти строки с любым конкретным подмножеством возможных ENUM значений.

SELECT * FROM `table` WHERE FIELD(`enum_column`, "alpha", "delta", "et cetera");

Если вы хотите использовать версию диапазона, вы можете использовать FIND_IN_SET("needle", "hay,stack") для возврата индекса, но сначала вам придется извлечь список ENUM из определения таблицы с помощью другого запроса.

0 голосов
/ 30 июля 2014

Создать функцию:

CREATE fEnumIndex(_table VARCHAR(50), _col VARCHAR(50), _val VARCHAR(50))
RETURNS INT DETERMINISTIC
BEGIN
    DECLARE _lst VARCHAR(8192);
    DECLARE _ndx INT;

    SELECT REPLACE(REPLACE(REPLACE(COLUMN_TYPE,''', ''',','),'enum(',''),')','')
    FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND
    TABLE_NAME=_table AND COLUMN_NAME=_col INTO _lst;
    SET _ndx = FIND_IN_SET(_val, _lst);
    RETURN _ndx;
END

Затем используйте его в запросе следующим образом:

SELECT * FROM MyTable WHERE Status < fEnumIndex('MyTable','Status','delta') ;

SELECT REPLACE(REPLACE(REPLACE(COLUMN_TYPE,''', ''',','),'enum(',''),')','') возьмет COLUMN_TYPE, например ENUM( 'alpha', 'beta', 'gamma', 'delta', 'omega' ), и превратит его в список через запятую: 'alpha, beta, gamma, delta, omega'. Тогда FIND_IN_SET(_val, _lst) получает индекс.

Единственное, с чем вам следует быть осторожным, это то, как вы определяете ENUM (с пробелами или без пробелов между элементами) и самый внутренний REPLACE (с пробелом в строке from_string или без него).

...