2008-11-16 10 views
8

Tengo una enumeración: ENUM('alpha', 'beta', 'gamma', 'delta', 'omega')¿Puedo comparar enums de MySQL?

Si ordeno mi tabla por esta columna, los obtengo en el orden correcto definido anteriormente.

Sin embargo, no puedo encontrar la manera de seleccionar un subconjunto de estos, p. Ej. todo antes del delta El uso de WHERE status < 'delta' solo devuelve alfa y beta, no gamma. Parece que MySQL usa una comparación de cadenas, no una comparación de índices enum.

Podría usar los números índices, es decir, WHERE status < 4, pero es un poco un olor a código (números mágicos) y puede romperse si inserto nuevos valores en la enumeración.

Respuesta

7

Está tratando de usar métodos de manipulación de datos en los metadatos, y esto seguramente será incómodo.

Esta es una buena razón para reemplazar el ENUM con una clave externa a una tabla de búsqueda. Entonces puede usar técnicas convencionales de manipulación de datos.

2

Puede usar FIELD(column, "string1", "string2", ...) para buscar filas con cualquier subconjunto particular de posibles valores ENUM.

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

Si desea utilizar la versión de gama, puede utilizar FIND_IN_SET("needle", "hay,stack") para devolver el índice, pero que tendrá que extraer la lista ENUM fuera de la definición de la tabla por primera vez con otra consulta.

3

acaba de encontrar el mismo problema. Si desea ordenar un campo de enumeración hay que echarlo a un tipo de cadena primero (categoría es mi campo de enumeración en el ejemplo):

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

Eazy!

+0

Esto suena como lo contrario de mi pregunta. Quería que el pedido fuera numérico, lo cual funciona bien. Mi problema fue con la cláusula WHERE. Aunque tal vez haya una forma de convertir el campo ENUM a un valor numérico y usar eso? Realmente no me importa ahora, lo pedí hace casi un año y ni siquiera recuerdo para qué era ... – DisgruntledGoat

0

crear una función:

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 

luego utilizarlo en una consulta de la siguiente manera:

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

El SELECT REPLACE(REPLACE(REPLACE(COLUMN_TYPE,''', ''',','),'enum(',''),')','') tomará el COLUMN_TYPE como ENUM('alpha', 'beta', 'gamma', 'delta', 'omega') y lo convertirá en una lista separada por comas: 'alpha, beta, gamma, delta, omega'. Luego, el FIND_IN_SET(_val, _lst) obtiene el índice.

Lo único que debe tener cuidado es cómo definir los ENUM (con o sin espacios entre los elementos) y el más interno REPLACE (con o sin espacio en from_string).