studio programacion para móviles libro edición desarrollo desarrollar curso aprende aplicaciones sql database-design

programacion - Mejores prácticas de diseño de bases de datos SQL(Direcciones)



manual de programacion android pdf (8)

Por supuesto, me doy cuenta de que no hay una "forma correcta" de diseñar una base de datos SQL, pero quería obtener algunas opiniones sobre qué es mejor o peor en mi situación particular.

Actualmente, estoy diseñando un módulo de entrada de pedidos (aplicación Windows .NET 4.0 con SQL Server 2008) y estoy dividido entre dos decisiones de diseño cuando se trata de datos que se pueden aplicar en más de un lugar. En esta pregunta me referiré específicamente a Direcciones.

Las direcciones pueden ser utilizadas por una variedad de objetos (pedidos, clientes, empleados, envíos, etc.) y casi siempre contienen los mismos datos (Dirección 1/2/3, Ciudad, Estado, Código postal, País, etc.). Originalmente iba a incluir cada uno de estos campos como una columna en cada una de las tablas relacionadas (por ejemplo, los pedidos contendrán la dirección 1/2/3, la ciudad, el estado, etc. y los clientes también contendrán este mismo diseño de columna). Pero una parte de mí desea aplicar los principios de DRY / Normalización a este escenario, es decir, tener una tabla llamada "Direcciones" a la que se hace referencia mediante la clave externa en la tabla correspondiente.

CREATE TABLE DB.dbo.Addresses ( Id INT NOT NULL IDENTITY(1, 1) PRIMARY KEY CHECK (Id > 0), Address1 VARCHAR(120) NOT NULL, Address2 VARCHAR(120), Address3 VARCHAR(120), City VARCHAR(100) NOT NULL, State CHAR(2) NOT NULL, Country CHAR(2) NOT NULL, PostalCode VARCHAR(16) NOT NULL ) CREATE TABLE DB.dbo.Orders ( Id INT NOT NULL IDENTITY(1000, 1) PRIMARY KEY CHECK (Id > 1000), Address INT CONSTRAINT fk_Orders_Address FOREIGN KEY REFERENCES Addresses(Id) CHECK (Address > 0) NOT NULL, -- other columns.... ) CREATE TABLE DB.dbo.Customers ( Id INT NOT NULL IDENTITY(1000, 1) PRIMARY KEY CHECK (Id > 1000), Address INT CONSTRAINT fk_Customers_Address FOREIGN KEY REFERENCES Addresses(Id) CHECK (Address > 0) NOT NULL, -- other columns.... )

Desde el punto de vista del diseño, me gusta este enfoque porque crea un formato de dirección estándar que es fácilmente modificable, es decir, si alguna vez tuviera que agregar Address4, simplemente lo agregaría en un lugar y no en cada tabla. Sin embargo, puedo ver que el número de JOIN necesarios para generar consultas puede volverse un poco loco.

Supongo que me pregunto si algún arquitecto SQL de nivel empresarial alguna vez ha utilizado este enfoque con éxito, o si el número de JOIN que crea crearía un problema de rendimiento.


Creo que hay un problema que usted no conoce y es que algunos de estos datos son sensibles al tiempo. No desea que sus registros muestren que envió un pedido a 35 State St, Chicago Il, cuando lo envió a 10 King Street, Martinsburg WV, pero el cliente se mudó dos años después de que se envió el pedido. Así que sí, construya una tabla de direcciones para obtener la dirección en ese momento siempre que cualquier cambio en la dirección de alguien como un cliente resulte en una nueva dirección no en el cambio de la dirección actual que rompería el historial de una orden.


Está bien tener una tabla de direcciones separadas.

Sin embargo, debe evitar la tentación de permitir que varias filas se refieran a la misma dirección sin un sistema apropiado para administrar opciones para que el usuario decida si y cómo cambiar una dirección divide una fila para el nuevo cambio de dirección, es decir, usted tiene la misma dirección para facturación y envío. Entonces, un usuario dice que su dirección está cambiando. Para empezar, las órdenes antiguas pueden (¿deberían?) Tener sus direcciones de envío retenidas, por lo que no puede cambiarlas en el lugar. Pero el usuario también podría necesitar decir que esta dirección que estoy cambiando solo va a cambiar el envío.


Estás en el camino correcto al dividir la dirección en su propia mesa. Agregaría un par de sugerencias adicionales.

  1. Considere tomar las columnas Address FK de las tablas Customers / Orders y crear tablas de unión en su lugar. En otras palabras, trate Clientes / Direcciones y Órdenes / Direcciones como relaciones de muchos a muchos en su diseño ahora para que pueda admitir fácilmente varias direcciones en el futuro. Sí, esto significa introducir más tablas y uniones, pero la flexibilidad que obtienes bien vale la pena.

  2. Considere crear tablas de búsqueda para entidades de ciudades, estados y países. Las columnas de ciudad / estado / país de la tabla de direcciones consisten en FK que apuntan a estas tablas de búsqueda. Esto le permite garantizar una ortografía consistente en todas las direcciones y le brinda un lugar para almacenar metadatos adicionales (por ejemplo, población de la ciudad) si es necesario en el futuro.


Lo que tiene que responder por sí mismo es la cuestión de si la misma dirección en el lenguaje cotidiano es realmente la misma dirección en su base de datos. Si alguien "cambia su dirección" (coloquialmente), realmente se vincula a otra dirección. La dirección per se solo cambia cuando se cambia el nombre de una calle, se lleva a cabo una reforma de código postal o se activa una bomba nuclear. Y esos son eventos raros (con suerte en su mayor parte). Ahí va su principal beneficio: cambiar en un lugar para múltiples filas (de múltiples tablas).

Si realmente debe cambiar una dirección para eso en su modelo, en el sentido de una UPDATE en la dirección de la tabla, eso puede funcionar o no para otras filas que se vinculen a ella. Además, en mi experiencia, incluso la misma dirección tiene que verse diferente para diferentes propósitos. Comprenda las diferencias semánticas y llegará al modelo correcto que represente mejor su mundo real.

Tengo varias bases de datos donde utilizo una tabla común de calles (que usa una tabla de ciudades (que usa una tabla de países, ...)). En combinación con un número de calle, considérelo como códigos geográficos (lat / lon), no como "nombres de calles". Las direcciones no se comparten entre diferentes tablas (o filas). Cambios en los nombres de las calles y en los códigos postales en cascada, otros cambios no.


No hay ningún valor práctico de tener una tabla separada para direcciones, por lo que puedo decir. Llevará a más combinaciones y códigos más complicados, y su frase "casi siempre contiene los mismos datos" me hace pensar que encontrará excepciones dolorosas.

Querría que las direcciones estén en una tabla separada si fueran entidades por derecho propio (lo que significa que tenían identidad y que importaba si dos objetos apuntaban a la misma dirección oa otras diferentes). Si este fuera el caso con su dominio, creo que sería totalmente evidente y no tendría que hacer esta pregunta. También otra respuesta tenía un punto válido sobre la mutabilidad de las direcciones, algo así como una dirección de envío es parte de un pedido y no debería poder cambiarse desde el pedido. Entonces, la dirección no tiene su propio ciclo de vida, y manejarla como una entidad separada solo puede generar confusión.

La "normalización" se refiere específicamente a eliminar redundancias de datos para que no tenga el mismo elemento representado en diferentes lugares. Aquí la única redundancia está en el DDL, no está en los datos, por lo que la "normalización" no es relevante aquí.


Normalmente, normalizarías los datos lo más posible, así que utiliza la tabla ''Direcciones''.

Puede usar vistas para desnormalizar los datos que luego usan índices y debe dar un método para acceder a los datos con referencias fáciles, mientras deja la estructura subyacente normalizada por completo.

El número de uniones no debería ser un problema importante, las uniones basadas en índices no son demasiados gastos generales.


Prefiero usar una tabla XREF que contenga una referencia FK a la tabla persona / empresa, una referencia FK a la tabla de direcciones y, generalmente, una referencia FK a una tabla de roles (HOME, OFFICE, etc.) para delinear el tipo real de dirección. También incluyo una bandera ACTIVA que me permite elegir ignorar la dirección anterior a la vez que conserva la capacidad de mantener un historial de direcciones.

Este enfoque me permite mantener múltiples direcciones de diferentes tipos para cada entidad primaria


Solo tengo algunas precauciones. Para cada uno de estos, hay más de una forma de solucionar el problema.

Primero, la normalización no significa "reemplazar texto con un número de identificación".

Segundo, no tienes una llave. Lo sé, tienes una columna declarada "PRIMARY KEY", pero eso no es suficiente.

insert into Addresses (Address1, Address2, Address3, City, State, Country, PostalCode) values (''President Obama'', ''1600 Pennsylvania Avenue NW'', NULL, ''Washington'', ''DC'', ''US'', ''20500''), (''President Obama'', ''1600 Pennsylvania Avenue NW'', NULL, ''Washington'', ''DC'', ''US'', ''20500''), (''President Obama'', ''1600 Pennsylvania Avenue NW'', NULL, ''Washington'', ''DC'', ''US'', ''20500''), (''President Obama'', ''1600 Pennsylvania Avenue NW'', NULL, ''Washington'', ''DC'', ''US'', ''20500''); select * from Addresses; 1;President Obama;1600 Pennsylvania Avenue NW;;Washington;DC;US;20500 2;President Obama;1600 Pennsylvania Avenue NW;;Washington;DC;US;20500 3;President Obama;1600 Pennsylvania Avenue NW;;Washington;DC;US;20500 4;President Obama;1600 Pennsylvania Avenue NW;;Washington;DC;US;20500

En ausencia de otras restricciones, su "clave principal" identifica una fila; no identifica una dirección. Identificar una fila generalmente no es lo suficientemente bueno.

En tercer lugar, "Dirección1", "Dirección2" y "Dirección3" no son atributos de las direcciones. Son atributos de las etiquetas postales. (Líneas en una etiqueta de correo). Esa distinción puede no ser importante para usted. Es realmente importante para mi

En cuarto lugar, las direcciones tienen una vida. Entre el nacimiento y la muerte, a veces cambian. Cambian cuando las calles se redirigen, los edificios se dividen, los edificios no se dividen y, a veces (estoy bastante seguro), cuando un empleado de la ciudad tiene una pinta demasiado. Los desastres naturales pueden eliminar comunidades enteras. A veces los edificios se vuelven a numerar. En nuestra base de datos, que es pequeña en comparación con la mayoría, alrededor del 1% por año cambia de esa manera.

Cuando una dirección muere, debes hacer dos cosas.

  • Asegúrese de que nadie use esa dirección para enviar por correo, enviar o lo que sea.
  • Asegúrese de que su muerte no afecte los datos históricos.

Cuando una dirección cambia, debe hacer dos cosas.

  • Algunos datos deben reflejar ese cambio. Asegúrate de que lo haga.
  • Algunos datos no deben reflejar ese cambio. Asegúrate de que no.

En quinto lugar, DRY no se aplica a claves externas. Todo su propósito es ser repetido. La única pregunta es ¿qué tan amplia es la clave? Un número de identificación es limitado, pero requiere una unión. (10 números de identificación pueden requerir 10 uniones). Una dirección es amplia, pero no requiere combinaciones. (Estoy hablando de una dirección adecuada, no de una etiqueta de envío).

Eso es todo lo que puedo pensar en la parte superior de mi cabeza.