2011-08-30 31 views
30

Quiero crear una columna element_type en una tabla (llamada discussion) que permite los valores de texto "lección" o "cuestionario" pero generará un error si se inserta cualquier otro valor en esa columna.En Postgres, ¿cómo restringe los posibles valores para una columna en particular?

entiendo que podría crear una tabla separada llamada element_types con columnas element_id (clave principal, int) y element_type (único, texto) y crear una clave externa en la tabla foreign_element_iddiscussion referencia element_types 's columna element_id. O, como alternativa, podría olvidar el element_id en total y simplemente configurar element_type como clave principal. Pero quiero evitar crear una nueva tabla.

¿Existe alguna manera más directa de restringir los valores posibles en una columna sin crear una nueva tabla?

+0

¿Por qué quiere evitar la creación de una mesa? no son particularmente costosos. – SingleNegationElimination

+2

No es tanto el costo de una tabla tanto como el desorden innecesario cada vez que quiero restringir los valores posibles, que en mi caso, es muy frecuente. –

Respuesta

57

Se podría añadir un CHECK CONSTRAINT:

ALTER TABLE distributors 
    ADD CONSTRAINT check_types 
    CHECK (element_type = 'lesson' OR element_type = 'quiz'); 

Aunque la OMI la opción más limpia sería la creación de un ENUM:

CREATE TYPE element_type AS ENUM ('lesson', 'quiz'); 
+11

Excelente. Gracias. Como nota para otros que pueden ser tan nuevos en Postgres como yo, CREATE TYPE crea un tipo definido por el usuario para ser utilizado como cualquier otro tipo, como int o texto. En este caso, se podría decir: 'CREATE TYPE element_type como ENUM ('lesson', 'quiz'); CREAR TABLA discusión ( type_of_element element_type; ); ' –

1

Este disparador inicia una excepción cada vez que alguien intenta insertar o actualizar una fila con un element_type inválido.

CREATE OR REPLACE FUNCTION check_discussion_element_type() RETURNS TRIGGER AS $$ 
DECLARE new_element_type varchar(25); 
BEGIN 
    SELECT element_type into new_element_type 
     FROM discussion 
     WHERE discussion.element_id = NEW.element_id; 

    IF new_element_type != 'lesson' AND new_element_type != 'quiz' 
     THEN RAISE EXCEPTION 'Unexpected discussion type'; 
    END IF; 
    RETURN NEW; 
END; 
$$ LANGUAGE plpgsql; 
create trigger t_check_discussion_element_type after update or insert on discussion for each row execute procedure check_discussion_element_type(); 

Si desea eliminar los tipos no modificables se puede adaptar para comprobar si existe el nuevo tipo en una tabla de tipos.

+1

Solución muy lenta y compleja, en comparación con una restricción de verificación o ENUM. –

16

Una sintaxis atajo es:

ALTER TABLE distributors 
    ADD CONSTRAINT check_types 
    CHECK (element_type IN ('lesson', 'quiz')); 

Esto se traduce a automaticolly:

CONSTRAINT check_types CHECK (element_type::text = ANY (ARRAY['lesson'::character varying, 'quiz'::character varying)) 

Enjoy ;-)

Cuestiones relacionadas