Pregunta

Aquí es una simplificación de mi base de datos:

Table: Property
Fields: ID, Address

Table: Quote
Fields: ID, PropertyID, BespokeQuoteFields...

Table: Job
Fields: ID, PropertyID, BespokeJobFields...

Luego tenemos otras tablas que se refieren a la Cita y Trabajo las tablas de forma individual.

Ahora necesito agregar un Mensaje tabla donde los usuarios pueden grabar mensajes telefónicos dejados por los clientes con respecto a los Trabajos y Citas.

Yo podría crear dos tablas idénticas (QuoteMessage y JobMessage), pero esto viola la SECA principal y parece desordenado.

Yo podría crear uno Mensaje tabla:

Table: Message
Fields: ID, RelationID, RelationType, OtherFields...

Pero esto me impide el uso de restricciones para hacer valer mis integridad referencial.También puede prever la creación de problemas con el devlopment lado usando Linq to SQL más tarde.

Hay una solución elegante a este problema, o soy yo al final van a tener que hackear algo juntos?

Quemaduras

¿Fue útil?

Solución

Crear un Mensaje de tabla, que contiene un único Mensaje y las distintas propiedades que se necesitan para almacenar un mensaje.

Table: Message
Fields: Id, TimeReceived, MessageDetails, WhateverElse...

Crear dos enlaces a tablas - QuoteMessage y JobMessage.Estos sólo contendrá dos campos cada uno, claves externas a la Oferta de Trabajo y el Mensaje.

Table: QuoteMessage
Fields: QuoteId, MessageId

Table: JobMessage
Fields: JobId, MessageId

De esta manera, se han definido las propiedades de los datos de un Mensaje en un sólo lugar (por lo que es fácil de extender, y consultar a través de todos los mensajes), pero también tiene la integridad referencial de la vinculación de las Comillas y los Puestos de trabajo a cualquier número de mensajes.De hecho, tanto una Cita de Trabajo y podría estar vinculada a la mismo mensaje (no estoy seguro de si es apropiado para su modelo de negocio, pero al menos el modelo de datos le da la opción).

Otros consejos

La otra única manera que se me ocurre es tener una base de tabla de Mensajes, con un Id y una TypeId.Sus subtablas (QuoteMessage y JobMessage), a continuación, hacer referencia a la tabla de base en ambos Idmensaje y TypeId - pero también tienen RESTRICCIONES CHECK en ellos para hacer cumplir sólo la adecuada MessageTypeId.

Table: Message
Fields: Id, MessageTypeId, Text, ...
Primary Key: Id, MessageTypeId
Unique: Id

Table: MessageType
Fields: Id, Name
Values: 1, "Quote" : 2, "Job"

Table: QuoteMessage
Fields: Id, MessageId, MessageTypeId, QuoteId
Constraints: MessageTypeId = 1
References: (MessageId, MessageTypeId) = (Message.Id, Message.MessageTypeId)
            QuoteId = Quote.QuoteId

Table: JobMessage
Fields: Id, MessageId, MessageTypeId, JobId
Constraints: MessageTypeId = 2
References: (MessageId, MessageTypeId) = (Message.Id, Message.MessageTypeId)
            JobId = Job.QuoteId

¿Esto qué comprar, en comparación con sólo un JobMesssage y QuoteMessage mesa?Se eleva un Mensaje a un ciudadano de primera clase, de modo que usted puede leer todos los Mensajes de una sola tabla.En cambio, su consulta ruta de un Mensaje de Cotización o de Empleo es 1 más unirse a distancia.Depende de tu aplicación de flujo, ya sea un buen cambio o no.

Como para 2 tablas idénticas violar SECO - yo no te colgó en eso.En la base de datos de diseño, es menos SECO y más acerca de la normalización.Si las 2 cosas que usted está modelado tienen los mismos atributos (columnas), pero en realidad son cosas diferentes (tablas), entonces es razonable tener varias tablas con esquemas similares.Mucho mejor que la inversa de sobrecargar diferentes cosas juntos.

@quemaduras

Ian respuesta (+1) es correcta [ver nota].El uso de muchos a muchos de la tabla QUOTEMESSAGE para unirse a QUOTE a MESSAGE es la más correcta modelo, pero dejará huérfanos MESSAGE registros.

Este es uno de esos raras los casos en que un disparador puede ser utilizado.Sin embargo, la precaución se debe aplicar para asegurar que el MESSAGE registro no puede ser asociado a un QUOTE y un JOB.

create trigger quotemessage_trg
on quotemessage
for delete
as
begin

delete 
from [message] 
where [message].[msg_id] in 
    (select [msg_id] from Deleted);

end

Nota a Ian, creo que hay una errata en la tabla de definición de JobMessage, donde las columnas debe ser JobId, MessageId (?).Me gustaría editar su cotización, pero puede que me tome un par de años para obtener ese nivel de reputación!

¿Por qué simplemente no tienen tanto QuoteId y JobId campos en la tabla de mensajes?O ¿un mensaje tiene que ser respecto a una cita o un puesto de trabajo y no tanto?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top