Esquema de base de datos que puede admitir propiedades especializadas

Necesito almacenar un conjunto de entidades, de las cuales hay varias versiones especializadas. Tienen algunas propiedades comunes, pero las especializadas contienen propiedades específicas para esa entidad.

Soluciones

El almacén de datos es un DBMS relacional, y esto no es para discusión 🙂 Específicamente, es el Microsoft SQL Server 2005.

Podría crear fácilmente una tabla para las propiedades comunes y luego una tabla para cada una de las versiones especializadas. Sin embargo, es probable que se tengan que agregar nuevas entidades a la solución más adelante y no quiero mantener tanto un modelo de objeto como un esquema de base de datos.

Otra idea es crear una mesa

reading(, extended_properties) 

y hacer que el campo extended_properties sea ​​algún tipo de serialización de las propiedades extendidas. Estaba pensando en JSON o XML. Lo más probable es que esté usando un marco ORM, pero todavía no lo he decidido. De cualquier forma, la representación del objeto de una entidad especializada a partir de la reading podría exponer un diccionario {extended_property_name, value} contiene los pares clave / valor analizados del campo extended_properties .

A partir de este http://msdn.microsoft.com/en-us/library/ms345117(SQL.90).aspx , recojo que los campos XML, combinados con esquemas para estos, dan la noción de XML escrito dentro del DBMS. Además, las consultas relacionadas con los contenidos XML en el campo extended_properties pueden tener esto en cuenta.

Lo que quiero

Comentarios sobre mis sugerencias de solución, principalmente la que tiene la tabla de reading y la serialización de las propiedades extendidas.

Además, me doy cuenta de que esta es una de las limitaciones del DBMS relacional en comparación con las tiendas basadas en clave / valor. Sin embargo, seguramente debe haber algunas técnicas de modelado para acomodar esto.

¡Cualquier comentario es muy apreciado!

Anders, no renuncie a su integridad o dureza, por ejemplo, tipo de seguridad.

(Respuesta que viene).

@Anders. No, para nada, la subtipificación está bien (la pregunta es qué formulario usas y cuáles son las ventajas / desventajas). No abandone ninguna fuerza o integridad o escriba seguridad o controles o DRI. El formulario que elija exigirá Cheques adicionales y tal vez un poco de código (depende de su plataforma).

Este tema aparece con frecuencia, pero el buscador siempre tiene una perspectiva estrecha; Sigo haciendo las mismas declaraciones (un subconjunto) de un conjunto que no cambia. La idea es evaluar todas las opciones. Así que estoy escribiendo un doc. Lamentablemente, está tardando más. Tal vez 4 páginas. No listo para publicar Pero los diagtwigs están terminados, creo que estás en la pelota, y puedes usarlo de inmediato.

Advertencia: solo ingenieros experimentados en construcción de proyectos
Carretera no apta para caravanas o lectores con un alto factor Eek

Enlace a ▶ Cuatro modelos de datos alternativos ◀ en documento en construcción. Disculpas por el desastre en el piso; Lo limpiaré pronto.

▶ Enlace a la notación IDEF1X ◀ para cualquier persona que no esté familiarizada con el estándar para modelar bases de datos relacionales.

  1. Todos son relacionales, con total integridad.

  2. Las opciones 6NF. Relacional hoy (SQL) no proporciona soporte para 6NF; no lo impide, simplemente no proporciona las estructuras 5NF➔6NF. Por lo tanto, necesita construir un pequeño catálogo, lo que algunos llaman “metadatos”. En realidad, es solo una extensión del catálogo SQL estándar (tablas sys). El nivel de control requerido se modela en cada opción.

  3. Esencialmente EAV hecho correctamente, con control total e integridad (tipo de seguridad, Integridad Referencial Declarativa, etc.) en lugar del desastre que suele ser.

Puede estar interesado en estas preguntas / respuestas relacionadas (en particular, consulte los Modelos de datos):

Múltiple Fixed vs Abstract Flexible

Problema relacionado con el esquema de la base de datos

Problema de diseño de base de datos “simple”

Respuesta a los comentarios

… De esta forma, podemos tomar fácilmente las filas de “Comentario” asociadas con una instancia de tipo especializada dada. ¿Es esta la manera de hacerlo, o lamentaré esa decisión más tarde? ¿Hay algún otro patrón que nos falta?

No estoy seguro de lo que quieres decir. Comentarios, Notas, Direcciones, terminan siendo utilizados (columnas residentes en) en muchas tablas, por lo que el método correcto es Normalizarlas; proporcionar una tabla para comentarios; que se hace referencia desde cualquier tabla que lo requiera. Aquí hay una tabla de Comentarios genérica. Se usa en Producto (el supertipo) porque usted indicó cualquier Producto. Puede utilizarse con la misma facilidad en algunos de los subtipos de productos, y no en otros; en cuyo caso, el FK estará en dichos Subtipos de Producto.

Su modelo de datos

¿Cuál es el propósito de la tabla ProductType en su ejemplo de Producto 5NF / subtipo? ¿Contiene una fila correspondiente a cada producto especializado, por ejemplo, ProductCPU? Supongo que indica qué especialización es el producto base.

(Pequeño error crítico en el diagtwig, corregido).

Sí exactamente.

En términos estándar relacionales (no los problemas incontrolados que pasan como bases de datos), el ProductType es el discriminador ; identifica cuáles de los subtipos de productos se aplican a este producto. Te dice a qué tabla de Subtipo de Producto necesitas unirte. Los dos juntos forman un Producto lógico. No olvides producir las Vistas, una para cada Tipo de Producto.

  • (Evalúe cómo cambia ProductType, exactamente qué papel desempeña, para cada uno de los cuatro modelos de datos).

  • “Generalización-especialización” es toda una terminología muda, OO; sin cruzar la línea y aprender de lo que Relational ha sido capaz durante 30 años. Si aprende un poco sobre Relacional, tendrá todo el poder; de lo contrario, estará limitado al enfoque OO muy limitado de todo (Ambler y Fowler tienen mucho por lo que responder). Por favor, lea esta publicación , desde el 11 de diciembre en adelante. Modelo de bases de datos relacionales Entidades, no objetos; no clases

Por ejemplo, al agregar un nuevo producto, querrá proporcionar, por ejemplo, una selección desplegable de los tipos de productos que es posible agregar. Según esta selección, se puede deducir en qué tablas colocar los datos. ¿Correcto? Lo siento por hablar sobre el código de la aplicación, pero solo necesito ponerlo en perspectiva

Sí. Y qué página (con campos) proporcionar a continuación, para que el usuario ingrese datos.

No hay problema para hablar sobre el código de la aplicación que usará el Rdb, van juntos como marido y mujer (no marido y esclavo).

  • Para sus clases de OO, asigne el árbol de clases al Rdb, una vez que haya terminado de modelar el Rdb, independientemente de cualquier aplicación que lo use. No de la otra manera. Y no depende de una aplicación.

  • Olvídese de “persistir”, tiene muchos problemas (actualizaciones perdidas, integridad de datos dañada, depuración problemática, contención masiva, etc.). Todas las actualizaciones del Rdb deben estar en Transacciones, con cumplimiento de ACID, disponibles por 30 años, pero Fowler y Ambler aún no lo han leído. Por lo general, eso significa un preact accionado almacenado.

El discriminante es un FK a una tabla de tipos como establecimos anteriormente. Denota qué especificación. subtipo al que se adhiere el tipo de base. Pero, ¿qué contiene la tabla discriminante en detalle?

¿No está claro desde el modelo de datos? ProducType CHAR(1) o (2). Name Char(30) (2). Name Char(30) .

Podría ser un texto fácil de mostrar que indique el tipo para fines de UI,

Sí, entre otras cosas, como el control, la restricción, etc., la eliminación de la ambigüedad al codificar o informar.

pero, ¿contiene también el nombre exacto de la tabla que contiene el tipo especializado?

No. Eso sería un poco demasiado físico para ser colocado en los datos. No permitido por principio.

Pero no es necesario.

Digamos que estoy interesado en el Producto con ID = 1. Tiene un discriminante que indica que es un ProductCPU. ¿Cómo haría para recuperar esta ProductCPU del código de su aplicación?

Eso será fácil si toma el modelo provisto y lo implementa (todas las tablas) como clases, correctamente, etc. El ejemplo que solicite no usará Vistas (que son para listas y uso más genérico). El pseudo-código sería:

  • dado el ProductId (Subtipo desconocido, por lo tanto, no debería estar sentado en una ventana específica de Subtipo), cargue solo el supertipo de Product
  • basado en Discriminator Product.ProductType , establecer indicadores, etc., y cargar el subtipo correspondiente, uno de ProductCPU; ProductMemory; ProductDisk; ProductTape ProductCPU; ProductMemory; ProductDisk; ProductTape ProductCPU; ProductMemory; ProductDisk; ProductTape ; etc.

  • He visto (y no estoy de acuerdo con) los métodos OO que cargan todos los subtipos para el ProductId dado a la vez: un subtipo es válido; y el rest no es válido El código aún tiene que restringirse a la clase válida para el Product basado en Product.ProductType .

Alternativamente, ej. donde está el contexto, el usuario está sentado en una ventana específica de Subtipo, ej. ProductCPU , con esa clase configurada, y solicita ProductId xxx. Luego use la vista ProductCPU . Si devuelve cero filas, no existe.

  • Puede haber un ProductDisk xxx, pero no un ProductCPU xxx. Cómo maneja eso, ya sea que indique que hay un Producto `xxx pero no es una CPU, o no, eso depende de los requisitos de la aplicación.

Para las listas, donde la aplicación rellena una cuadrícula, ProductId , use las vistas (una para cada una) para cargar cada cuadrícula. Ese SQL se basa en la unión, y no necesita referirse a ProductType .

Me gustaría ir personalmente al método “crear una tabla para las propiedades comunes y luego una tabla para cada una de las versiones especializadas”.

Motivo: usted dice que su implementación se realizará en un RDBMS y esto no es negociable. Multa. Sin embargo, volcar cosas sin estructura como blob serializadas en un campo DB va en contra de la filosofía de diseño de RDBMS, por lo que tendrá un impacto severo en la eficiencia a menos que esté de acuerdo con la idea de tratar el campo * extended_properties * como un opaco blob, como un gif u otro objeto binario.

En otras palabras, olvide consultar (de manera eficiente) para “todos los objetos que tengan propiedades extendidas COLOR = ROJO”.

El problema que tiene (describir taxonomías OO en un RDBMS) definitivamente no es nuevo. Eche un vistazo a esto para obtener una descripción detallada de las opciones.

Este es un ejemplo clásico del patrón de diseño gen-spec. Gen-spec está cubierto en cada tutorial sobre modelado de objetos, porque se maneja por herencia. Con frecuencia se pasa por alto en tutoriales sobre modelado de datos relacionales. Pero está bien entendido.

Haga una red de scope web sobre “generalización, especialización, modelado relacional”. Verá varios artículos sobre cómo configurar una sola tabla para la clase general y una tabla para cada clase especializada. Los artículos te ayudarán con el diseño de la clave extranjera. En particular, la clave principal de cada tabla especializada cumple una doble función. También es una clave externa a la tabla generalizada.

Esto no te resultará muy familiar si estás acostumbrado a modelar objetos. Pero encontrarás que funciona bien. Y la solución ofrecida por la mayoría de los artículos no es dinámica, por lo que tendrá que hacer algo de DDL cada vez que se descubra una nueva subclase especializada.

Aquí hay cinco ejemplos del SO. Cuál usar dependerá del problema real que está resolviendo y su preferencia.

En general, desaconsejaría serializar datos en los campos DB.

Si hay relativamente pocas versiones especializadas de una entidad, simplemente podría usar subtipos como en estos ejemplos: ejemplo uno , ejemplo dos .

Para valores grandes de propiedades, o si las propiedades deben definirse dinámicamente (sin cambios de esquema), busque una implementación del patrón de observación como en estos ejemplos: ejemplo tres , ejemplo cuatro ; o en la llamada 6ta forma normal como se describe en: ejemplo cinco . Tenga en cuenta que el “patrón de observación” es una versión simplificada de la 6ª NF.

Esta técnica puede tener algunos problemas con el diseño y el rendimiento adecuados, pero parece que necesita un compromiso con la flexibilidad.

En lugar de tener que crear tablas específicas o incluso un nuevo campo para cada propiedad, podría tener una tabla (y será bastante grande) para propiedades únicas:

 Unique_Property_ID , FK_To_Some_Entity (Not sure what entity these link to: customers, bills, etc.) , Property_Type Not the data type but a link to a table describing this entity) , Property_Value (Difficult to determine if all of your values will be of the same type: string, int, date, etc.) 

Ejemplo: un concesionario de autos usados ​​que necesita rastrear complementos para diferentes marcas y modelos (nunca saben lo que van a obtener). Algunos registros pueden verse así:

 VehicleID Property Type Property Value 3 Sound System Bose 3 Hybrid System Battery 7 Starter Type Hand Crank 7 Passenger Seat Rumble 9 Starter Type Kick Start 9 Passenger Seat Side Car 

Cada valor para cada conjunto | tipo de propiedad tendría su propio registro.

Otro problema es cuando desea que cada propiedad se represente como una columna, tendrá que transponer esta tabla.