2011-09-22 20 views
5

Aquí está un ejemplo sencillo:¿Cómo especifico una dirección de envío predeterminada del cliente en una tabla de base de datos?

Supongamos que tengo una tabla de clientes que tiene una relación de uno a varios con la tabla de direcciones (un cliente puede tener múltiples direcciones de envío, pero una dirección de envío sólo puede pertenecer a un solo cliente)

Customer Table 
------------- 
customer_id (PK) 


Address Table 
------------- 
address_id (PK) 
customer_id (FK) 

Ahora quiero que cada cliente pueda especificar una dirección de envío predeterminada.

Puedo pensar en 2 maneras pero ambas tienen inconvenientes.

Opción 1

añadir una columna booleana para la tabla de direcciones llamado "is_default".

Pros

  1. consultas de selección son simples
  2. sencillo para otras personas a entender si ven el modelo DB

Contras

  1. La aplicación es fo para aplicar y mantener la restricción de "solo una fila puede ser una predeterminada".
  2. La actualización del campo predeterminado es un problema porque requiere que la aplicación compruebe y restablezca la opción predeterminada anterior.

Opción 2

Agregar una columna a la tabla de clientes llamado "address_id" y que sea una clave externa (también permiten valores nulos en caso de que no existe ninguna dirección).

Pros

  1. fácil de actualizar la dirección por defecto si el usuario decide cambiarlo.
  2. La base de datos mantiene la restricción de "solo una fila puede ser una predeterminada".

Contras

  1. tengo que añadir una nueva columna indexada a la tabla de clientes cada vez que decide añadir algún tipo de metadatos predeterminado.

  2. parece un truco

Mi pregunta es, ¿hay una forma estándar para manejar este tipo de escenario que estoy pasando por alto? Por supuesto, hay otras opciones (¿tal vez crear una tabla de opciones predeterminadas de EAV?), Pero preferiría mantenerlo lo más simple posible porque el cambio se realiza en una base de códigos existente, así que no quiero romper nada.

Respuesta

1

(tal vez la creación de una tabla de opciones por defecto EAV?)

Me gustaría hacer esto, especialmente si usted está preocupado por romper el código existente.

Customer_Defaults 
------------------------------------ 
customer_id       PK, FK -> Customer 
default_shipping_address_id   FK -> Address 

¿No es así de ordenado? Al agrupar todo en una mesa separada, dejas las tablas existentes en paz. Si está utilizando algún tipo de capa ORM, el objeto sobre esta nueva tabla se puede consultar directamente, y luego puede caminar hasta el objeto Address. No es necesario incluso presentar el nuevo objeto a los objetos existentes de Cliente o Dirección.

+0

pensé en eso, pero entonces tendría que crear una nueva "tabla de valores predeterminados" para cada mesa que requiere una tarjeta de crédito predeterminada es decir, las cuentas –

+0

@BillH: ¿Por qué? No hay nada que le impida agregar otra columna, 'default_credit_card_id', que apunta a la tabla Credit_Card. El nombre de la tabla es suficientemente genérico para capturar * todos * los valores predeterminados para el cliente. – Mac

0

Cuando crezca requisitos nuevos, piense en tablas nuevas. Aquí hay dos maneras diferentes de abordar su problema. El primero es menos estricto que el segundo. (Utilizaría el segundo.) Asumiré que "Address Table" se llama "customer_addresses".

create table default_shipping_addresses (
    customer_id integer primary key references customers (customer_id), 
    shipping_addr_id integer not null unique references addresses (addr_id) 
); 

create table default_shipping_addresses (
    customer_id integer primary key references customers (customer_id), 
    shipping_addr_id integer not null unique references addresses (addr_id), 

    -- Add a UNIQUE constraint on customer_addresses (customer_id, address_id). 
    -- Since address_id is the primary key, it's unique, so (customer_id, 
    -- address_id) will also be unique. But you need the UNIQUE constraint to 
    -- allow a foreign key to reliably reference it, even in MySQL. 
    foreign key (customer_id, shipping_addr_id) 
    references customer_addresses (customer_id, address_id) 
); 
+0

¿No podría simplemente hacer una clave primaria compuesta entre customer_id y shipping_addr_id con 2 claves externas apuntando a sus fuentes respectivas? –

Cuestiones relacionadas