2009-04-17 12 views
18

¿Cómo implementaría un campo de enumeración en una base de datos que no admite enumeraciones? (es decir, SQLite)¿Cómo manejar enumeraciones sin campos enum en una base de datos?

Los campos deben ser fácilmente navegados con "field =?" así que usar cualquier tipo de serialización de datos es una mala idea.

+0

Si este es un duplicado, por favor se agradable. Busqué la respuesta en StackOverflow antes de preguntar. – epochwolf

Respuesta

49

Utilizando una clave externa a una tabla de búsqueda es el enfoque que uso. De hecho, uso esto incluso cuando utilizo una base de datos que admite ENUM (por ejemplo, MySQL).

Para simplificar, puedo omitir el omnipresente "id" para la tabla de búsqueda, y simplemente usar el valor real que necesito en mi tabla principal como la clave principal de la tabla de búsqueda. De esta forma, no es necesario que se una para obtener el valor.

CREATE TABLE BugStatus (
    status   VARCHAR(20) PRIMARY KEY 
); 

INSERT INTO BugStatus (status) VALUES ('NEW'), ('OPEN'), ('FIXED'); 

CREATE TABLE Bugs (
    bug_id   SERIAL PRIMARY KEY, 
    summary   VARCHAR(80), 
    ... 
    status   VARCHAR(20) NOT NULL DEFAULT 'NEW', 
    FOREIGN KEY (status) REFERENCES BugStatus(status) 
); 

Es cierto que el almacenamiento de las cadenas tiene más espacio que la aplicación de ENUM de MySQL, pero a menos que la tabla en cuestión cuenta con millones de filas, poco importa.

Otras ventajas de la tabla de búsqueda es que usted puede agregar o quitar un valor de la lista con un simple INSERT o DELETE, mientras que con ENUM usted tiene que utilizar ALTER TABLE para redefinir la lista.

También intente consultar la lista actual de valores permitidos en un ENUM, por ejemplo para rellenar una lista de selección en su interfaz de usuario. ¡Es una gran molestia! Con una tabla de búsqueda, es fácil: SELECT status from BugStatus.

También puede agregar otras columnas de atributos a la tabla de búsqueda si es necesario (por ejemplo, para marcar las opciones disponibles solo para los administradores). En un ENUM, no puede anotar las entradas; solo son valores simples.

Otra opción además de una tabla de consulta sería utilizar CHECK limitaciones (siempre y cuando la base de datos de los apoya - MySQL no lo hace):

CREATE TABLE Bugs (
    bug_id   SERIAL PRIMARY KEY, 
    summary   VARCHAR(80), 
    ... 
    status   VARCHAR(20) NOT NULL 
    CHECK (status IN ('NEW', 'OPEN', 'FIXED')) 
); 

Pero este uso de una restricción CHECK sufre de la misma desventajas como ENUM: difícil cambiar la lista de valores sin ALTER TABLE, difícil de consultar la lista de valores permitidos, valores difíciles de anotar.

PD: el operador de comparación de igualdad en SQL es un solo =. El doble == no tiene significado en SQL.

+0

Gracias por el = vs. == cosa :) Ha pasado un tiempo desde que he usado SQL directamente. – epochwolf

+0

excelente respuesta, +1 de mí. – Brann

+0

Una pregunta un poco vieja, pero respuesta increíble. Vota arriba. –

-1

Yo usaría un varchar. ¿No es esta una opción para ti?

+0

El uso de un VARCHAR daría lugar a datos desnormalizados. Si desea cambiar el nombre del valor enum, se requiere una actualización en toda la tabla, en lugar de simplemente cambiar una sola fila en una tabla de referencia. –

1

Es, básicamente, tiene dos opciones:

  • uso un campo entero

  • utilizar un campo varchar

abogaría personalmente el uso de varchars, porque usted ganó' No rompa nada si cambia su enumeración + los campos son legibles por el ser humano, pero los ints tienen algo de pro, como el rendimiento (el tamaño de los datos es un ejemplo obvio)

2

Para restringir los valores posibles, utilizaría una clave externa en una tabla que contiene los elementos de la enumeración.

Si no desea SUSCRIBIRSE para hacer sus búsquedas, convierta la clave en varchar si las UNIONES NO son un problema, luego convierta la clave en INT y no se una a menos que necesite buscar en ese campo.

Tenga en cuenta que poner sus enumeraciones en el DB impide la verificación en tiempo de compilación de los valores en su código (a menos que duplique la enumeración en el código). He encontrado que esto es un gran inconveniente.

0

Esto es lo que hice recientemente

En mi hibernación asignada POJO- me quedé con el tipo del miembro como cadena y es VARCHAR en la base de datos.

El colocador para esta toma una enumeración Hay otro colocador que tiene String pero esto es privada (o puede mapear el campo directamente- si eso es lo que usted prefiere.)

Ahora bien, el hecho de que estoy usando La cadena está encapsulada de todos. Para el resto de la aplicación, mis objetos de dominio usan enum. Y en lo que respecta a la base de datos, estoy usando String.

Si me perdí tu pregunta, me disculpo.

+0

Esto tiene sentido. Ruby on Rails permitiría el mismo comportamiento con validaciones como bonificación. – epochwolf

Cuestiones relacionadas