Estimados, pido disculpas por sumarme a este hilo, es posible que nos estemos llendo de tema. Pero lo creo interesante
La primera respuesta de Jaime del 14 de abril, fue impecable. Los viejitos como yo, lo llamamos exclucion mutua, luego un par de mensajes mas tarde Alvaro mejora haciendo mas corto la constrain. Ahora para ver otras opciones de resolver el problema, dependiendo del entorno de cada coso en particular, es posible que con herencia se tengan ventajas. (muy dificil que pase... pero pasa) Obvio que es mejor o que peor siempre es para discutir. Les paso un scripts con dos modos de resolver el problema con herencia, de los cuales yo uso el segundo ( obvio con mas trabajo, pues en este ejemplo esta resumido) ---------- --- Modo 1 --- Usando herencia de postgres, pero en mi ignorancia sobre el tema, lo debo complementar con un trigger, pues en herencia no se propaga de la clase padre a las hijas --- las primary key y si inserto en la hija en realidad no inserta en el padre --- de modo que no es una solucion valida, yo en realidad siempre uso el modo 2 en estos casos, pero el modo 1 es mas didactico --------- drop schema univ cascade; create schema univ; CREATE DOMAIN univ.tipos_catedras AS integer DEFAULT 1 CONSTRAINT tipos_catedras_check CHECK (VALUE = ANY (ARRAY[0, 1])); COMMENT ON DOMAIN univ.tipos_catedras IS '1= Materias 0= Talleres'; create table univ.catedras ( id serial not null primary key, tipo_catedra univ.tipos_catedras, nombre text ); create table univ.materias ( profesor text, etc text ) INHERITS (univ.catedras); create table univ.talleres ( jefe_trabajo_practico text, etc text ) INHERITS (univ.catedras); CREATE OR REPLACE FUNCTION univ.f1_fnc() RETURNS trigger AS $BODY$ DECLARE v_c integer; BEGIN IF (TG_OP = 'INSERT') THEN if TG_TABLE_NAME = 'materias' then v_c := 1; else v_c := 0; end if; insert into univ.catedras (id,tipo_catedra,nombre) values ( NEW.id,v_c,NEW.nombre); RETURN NEW; ELSE RAISE WARNING 'se llamo mal: %, at %',TG_OP,now(); RETURN NULL; END IF; END; $BODY$ LANGUAGE plpgsql VOLATILE SECURITY DEFINER; CREATE TRIGGER materias_trg BEFORE INSERT ON univ.materias FOR EACH ROW EXECUTE PROCEDURE univ.f1_fnc(); CREATE TRIGGER talleres_trg BEFORE INSERT ON univ.talleres FOR EACH ROW EXECUTE PROCEDURE univ.f1_fnc(); insert into univ.materias ( tipo_catedra, nombre, profesor, etc ) values (1,'tejido','prf1','etc'); insert into univ.materias ( tipo_catedra, nombre, profesor, etc ) values (1,'lavar ropa','prf2','etc2'); insert into univ.talleres ( tipo_catedra, nombre, jefe_trabajo_practico, etc ) values (0,'modo correcto de apretar tuercas','jefe1','etc8'); insert into univ.talleres ( tipo_catedra, nombre, jefe_trabajo_practico, etc ) values (0,'modo correcto de aflojar tuercas','cocacola','etc9'); insert into univ.materias ( tipo_catedra, nombre, profesor, etc ) values (1,'otra cosa','prf2','etc32'); insert into univ.talleres ( tipo_catedra, nombre, jefe_trabajo_practico, etc ) values (0,'modo correcto de clavar clavitos','jefe2','etc6'); select * from univ.catedras order by id; select * from univ.materias; select * from univ.talleres; drop table univ.inscripciones; create table univ.inscripciones ( id serial not null primary key, alumno text, fecha timestamp, loquefuera text, catedra integer not null references univ.catedras(id) ); insert into univ.inscripciones (alumno,catedra) values ('Jose',1); insert into univ.inscripciones (alumno,catedra) values ('Jose',2); insert into univ.inscripciones (alumno,catedra) values ('Jose',3); insert into univ.inscripciones (alumno,catedra) values ('Jose',4); insert into univ.inscripciones (alumno,catedra) values ('Jose',5); select * from univ.catedras where id= 1 ---------- --- Modo 2 --- lo mismo pero sin herencia o con una simulacion de herencia --------- drop schema univ1 cascade; create schema univ1; CREATE DOMAIN univ1.tipos_catedras AS integer DEFAULT 1 CONSTRAINT tipos_catedras_check CHECK (VALUE = ANY (ARRAY[0, 1])); COMMENT ON DOMAIN univ1.tipos_catedras IS '1= Materias 0= Talleres'; create table univ1.catedras ( id serial not null primary key, tipo_catedra univ1.tipos_catedras ); create table univ1.materias ( id integer not null primary key references univ1.catedras(id), nombre text, profesor text, etc text ); create table univ1.talleres ( id integer not null primary key references univ1.catedras(id), nombre text, jefe_trabajo_practico text, etc text ); CREATE OR REPLACE FUNCTION univ1.f1_fnc() RETURNS trigger AS $BODY$ DECLARE v_c integer; BEGIN IF (TG_OP = 'INSERT') THEN if NEW.id is null then NEW.id := nextval('univ1.catedras_id_seq'); end if; if TG_TABLE_NAME = 'materias' then v_c := 1; else v_c := 0; end if; insert into univ1.catedras (id,tipo_catedra) values ( NEW.id,v_c); RETURN NEW; ELSE RAISE WARNING 'se llamo mal: %, at %',TG_OP,now(); RETURN NULL; END IF; END; $BODY$ LANGUAGE plpgsql VOLATILE SECURITY DEFINER; CREATE TRIGGER materias_trg BEFORE INSERT ON univ1.materias FOR EACH ROW EXECUTE PROCEDURE univ1.f1_fnc(); CREATE TRIGGER talleres_trg BEFORE INSERT ON univ1.talleres FOR EACH ROW EXECUTE PROCEDURE univ1.f1_fnc(); insert into univ1.materias ( nombre, profesor, etc ) values ('tejido','prf1','etc'); insert into univ1.materias ( nombre, profesor, etc ) values ('lavar ropa','prf2','etc2'); insert into univ1.talleres ( nombre, jefe_trabajo_practico, etc ) values ('modo correcto de apretar tuercas','jefe1','etc8'); insert into univ1.talleres ( nombre, jefe_trabajo_practico, etc ) values ('modo correcto de aflojar tuercas','cocacola','etc9'); insert into univ1.materias ( nombre, profesor, etc ) values ('otra cosa','prf2','etc32'); insert into univ1.talleres ( nombre, jefe_trabajo_practico, etc ) values ('modo correcto de clavar clavitos','jefe2','etc6'); select * from univ1.catedras order by id; select * from univ1.materias; select * from univ1.talleres; drop table univ1.inscripciones; create table univ1.inscripciones ( id serial not null primary key, alumno text, fecha timestamp, loquefuera text, catedra integer not null references univ1.catedras(id) ); insert into univ1.inscripciones (alumno,catedra) values ('Jose',1); insert into univ1.inscripciones (alumno,catedra) values ('Jose',2); insert into univ1.inscripciones (alumno,catedra) values ('Jose',3); insert into univ1.inscripciones (alumno,catedra) values ('Jose',4); insert into univ1.inscripciones (alumno,catedra) values ('Jose',5); select * from univ1.inscripciones select * from univ1.catedras where id= 1 Desde ya muchas gracias por vuestra tolerancia a un mail tan largo, y espero que le fuera de utilidad a alguna persona. Saludos VHR El 5 de mayo de 2014, 18:30, Jaime Casanova <ja...@2ndquadrant.com>escribió: > 2014-05-05 13:35 GMT-05:00 Guillermo E. Villanueva <guillermo...@gmail.com > >: > > Si si, eso es lo que dijo Alvaro y no lo discuto. Solo digo que no es >> bueno que ya por diseño uno de los dos campos va a ser NULL en todas las >> filas. >> >> > > no por diseño, es la implementación de un diseño en el que se usa la misma > tabla para almacenar ambos datos. > la otra implementación posible es la que mencione, un campo tipo y usar el > mismo campo con un constraint trigger para RI > > cual es mejor? probablemente la que incluye dos campos. un campo null > ocupa un solo bit (lo que se traduce en al menos 1 byte pero si ya tienes > campos en null no usas nada adicional) y como ventaja adicional no debes > inventar la rueda tratando de hacer un constraint trigger que simule el FK > > mientras que en la otra opción, son dos campos not null (es decir que > usamos al menos 5 bytes) mas el constraint trigger > > ahora, la estructura física de la tabla es solo la forma en que > implementas el diseño lógico y no deberías alterar el diseño lógico > pensando solo en la estructura física sino al reves > > -- > Jaime Casanova www.2ndQuadrant.com > Professional PostgreSQL: Soporte 24x7 y capacitación > Phone: +593 4 5107566 Cell: +593 987171157 >