2008-11-16 3 views
8

У меня есть перечисление: ENUM('alpha', 'beta', 'gamma', 'delta', 'omega')Могу ли я сравнивать перечисления MySQL?

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

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

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

ответ

7

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

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

2

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

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

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

3

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

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

Eazy!

+0

Это звучит как противоположность моего вопроса. Я хотел, чтобы заказ был числовым, и все в порядке. Моя проблема заключалась в предложении WHERE. Хотя, возможно, есть способ конвертировать поле ENUM в числовое значение и использовать его? Теперь для меня это не имеет значения, я спросил об этом почти год назад, и я даже не помню, для чего это было ... – DisgruntledGoat 2009-10-13 15:35:41

0

Создание функции:

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).

Смежные вопросы