Ejemplo simple: hay una mesa de clientes.
create table Customers (
id integer,
constraint CustomersPK primary key (id)
)
Todos los demás datos en la base de datos deben vincularse a a Customer
, por ejemplo, se Orders
ve así:
create table Orders (
id integer,
customer integer,
constraint OrdersPK primary key (customer, id),
constraint OrdersFKCustomers foreign key (customer) references Customers (id)
)
Supongamos que ahora hay una tabla que vincula a Orders
:
create table Items (
id integer,
customer integer,
order integer,
constraint ItemsPK primary key (customer, id),
constraint ItemsFKOrders foreign key (customer, order) references Orders (customer, id)
)
¿Debo agregar una clave externa separada de Items
a Customers
?
...
constraint ItemsFKCustomers foreign key (customer) references Customers (id)
Una imagen en su lugar: ¿debo agregar la línea discontinua / FK?
Editar: he agregado definiciones de clave principal a las tablas. Me gustaría volver a repetir el punto que mencioné anteriormente: la base de datos está básicamente aislada por los clientes, como una medida de corrección / seguridad. Por lo tanto, todas las claves primarias contienen la customer
ID.
database-design
foreign-key
vektor
fuente
fuente
Respuestas:
Creo que esta es la idea original.
Lo primero que debe notar es que la PK en la tabla LineItem tiene tres atributos
{CustomerID, CustomerOrderNo, OdrerItemNo}
, en lugar de solo dos en su ejemplo.La segunda cosa a tener en cuenta es la confusión resultante del uso del
id
nombre genérico para un atributo.Lo
CustomerOrderNo
ideal sería (1,2,3 ..) para cada cliente yOrderItemNo
(1,2,3 ...) para cada pedido.Bueno, esto es bueno si es posible, pero requiere una consulta que busque el valor máximo anterior, como
que a menudo no se prefiere en entornos de alto volumen de transacciones, por lo que es común ver estos reemplazados por un incremento automático, que esencialmente sirve para el mismo propósito. Es cierto que este incremento automático ahora es único, por lo tanto, puede usarse como una CLAVE, pero puede optar por considerarlo como un compromiso necesario para el
OrderItemNo
.Entonces, con algunos cambios de nombre
CustomerOrderNo -> OrderNo
yOrderItemNo
->ItemNo
puede llegar a este modeloEntonces, si nos fijamos en
Order
lo siguiente, son únicosTenga en cuenta que
{CustomerID, OrderNo}
se propaga a laLineItem
para servir como un FK.Si entrecierra un poco los ojos, esto está cerca de su ejemplo, pero
PKs {ItemNo} and {OrderNo}
solo con , en lugar de dos PK de columna de su ejemplo.Ahora la pregunta es, ¿por qué no simplificar a algo como esto?
Lo cual está bien, pero introduce dependencia de la trayectoria - no se puede unir
LineItem
conCustomer
directamente, debe utilizarOrder
en la combinación.Prefiero el primer caso cuando sea posible: eliges tu favorito. Y obviamente, no hay necesidad de FK directo de
LineItem
aCustomer
en estos tres casos.fuente
El "artículo" no debe hacer referencia al "cliente" directamente, porque esto está implícito en el "pedido" del artículo. Por lo tanto, no necesitará las columnas "cliente" en la tabla de "artículos".
La relación del artículo con el cliente se garantiza con la clave externa existente.
Si orders.id es una columna de identidad, considere eliminar items.customer por completo.
fuente
customer
en todas las tablas (y, por lo tanto, aislar el DB) es un enfoque inusual. Debo confesar que es algo que he visto en mi trabajo anterior. ¿Tiene algún sentido para ti? ¿Has visto tal diseño antes?