2009-07-24 9 views
6

Hola estoy luchando un poco con esto y podría usar algunas ideas ...Registros vinculados a cualquier tabla?

Digamos que mi base de datos tiene las siguientes tablas; clientes supplers SalesInvoices PurchaseInvoices Monedas

, etc, etc

Me gustaría ser capaz de añadir un registro de "Notas" a cualquier tipo de registro

Las notas de la tabla quisiera esta

NoteID  Int (PK) 
NoteFK  Int 
NoteFKType Varchar(3) 
NoteText  varchar(100) 
NoteDate  Datetime 

Donde NoteFK es el PK de un cliente o proveedor etc. y NoteFKType dice qué tipo de reco la nota es contra

Ahora me doy cuenta de que no puedo agregar un FK que hace referencia a varias tablas sin que NoteFK deba estar presente en todas las tablas.

Entonces, ¿cómo diseñaría lo anterior? La nota FK necesita estar en cualquiera de las tablas anteriores

Cheers, Daniel

+0

¿Se requiere integridad referencial a nivel de base de datos, o puede vivir con integridad referencial gestionada por la aplicación? – tschaible

Respuesta

-2

¿Por qué no hacerlo a la inversa y tienen una clave externa en otras tablas (clientes, proveedores, etc, etc) a NotesID. De esta manera tiene un mapeo uno a uno.

+1

¿Qué pasa si él quiere tener una relación de uno a muchos? Muchas notas para una entidad.Él terminaría con muchas tablas adicionales que no son requeridas. – maciejkow

+1

Esto no garantiza que el mismo NoteID no se haga referencia más de una vez. Pero eso depende de los requisitos comerciales. –

+0

Si hay una necesidad de uno a muchos, podemos tener almacenados los notesIDs separados por comas (esto es solo una solución alternativa) en lugar de tener diferentes tablas para enlazar. –

0

Puede agregar un campo GUID a las tablas Clientes, Proveedores, etc. Luego, en la tabla de Notas, cambie la clave externa para hacer referencia a ese GUID.

Esto no ayuda a la integridad de los datos. Pero hace que las relaciones M-to-N sean fácilmente posibles para cualquier cantidad de tablas y le evita tener que definir una columna NoteFKType en la tabla de Notas.

2

Creo que su diseño está bien, si puede aceptar el hecho, que el sistema db no verificará si una nota está haciendo referencia a una entidad existente en otra tabla o no. Es el único diseño que puedo pensar que no requiere duplicación y es escalable para más tablas.

La forma en que lo diseñó, cuando agrega otro tipo de entidad para el que desea tener notas, no tendrá que cambiar su modelo. Además, no es necesario que incluya columnas adicionales en su modelo existente o tablas adicionales.

Para garantizar la integridad de los datos, puede crear un conjunto de desencadenantes o alguna solución de software que limpie la tabla de notas de vez en cuando.

3

Tiene que aceptar la limitación que no puede enseñar a la base de datos sobre esta restricción de clave externa. Por lo tanto, tendrá que prescindir de la comprobación de integridad (y de las eliminaciones en cascada).

Su diseño está bien. Es fácilmente extensible a tablas adicionales, puede tener múltiples notas por entidad, y las tablas de destino ni siquiera necesitan conocer la función de notas.

Una ventaja que este diseño tiene sobre el uso de una tabla de notas separadas por mesa entidad es que se puede ejecutar fácilmente las consultas entre todas las notas, por ejemplo "notas más recientes", o "todas las notas creadas por un usuario determinado".

En cuanto al argumento de que la tabla crece demasiado, dividirla en decir cinco tabla reducirá la tabla a aproximadamente un quinto de su tamaño, pero esto no hará ninguna diferencia para el acceso basado en índice. Las bases de datos están diseñadas para manejar grandes tablas (siempre que estén correctamente indexadas).

0

Puede implementar fácilmente la tecla "multi" -extranjera con activadores. Los disparadores le darán un mecanismo muy flexible y puede hacer las comprobaciones de integridad que desee.

1

Lo pensaría dos veces antes de hacer lo que sugiere. Puede parecer simple y elegante en el corto plazo, pero si está realmente interesado en la integridad y el rendimiento de los datos, entonces tener las tablas de notas separadas para cada tabla padre es el camino a seguir. A lo largo de los años, he abordado este problema utilizando las soluciones que se encuentran en las otras respuestas (desencadenantes, GUID, etc.). Llegué a la conclusión de que la complejidad añadida y la pérdida de rendimiento no valen la pena. Al tener tablas de notas separadas para cada tabla padre, con restricciones de clave externa apropiadas, las búsquedas y las uniones serán simples y rápidas. Al combinar los elementos relacionados en una sola tabla, la sintaxis de unión se vuelve fea y la tabla de notas crecerá y será lenta.

+0

+1 Acepto y puedo responder por esto. A la larga, solo está complicando su solución y agregando deuda técnica que eventualmente tendrá que ser tratada. –

+0

Por otro lado, puede con su solución actual ejecutar consultas en todas las notas, lo que sería difícil con varias tablas de notas. – Thilo

+1

@Thilo: teniendo en cuenta los consejos de Michael, una vista SQL es una forma más apropiada de agregar todas las tablas de notas en una única fuente de consulta. –

1

Estoy de acuerdo con Michael McLosky, hasta cierto punto.

La pregunta en mi mente es: ¿Cuál es el costo técnico de tener varias tablas de notas?

En mi opinión, es preferible consolidar la misma funcionalidad en una sola tabla. También facilita la creación de informes y otros desarrollos posteriores. Sin mencionar mantener la lista de tablas más pequeña y fácil de administrar.

Es un acto de equilibrio, debe intentar predeterminar tanto los beneficios como los costos de hacer algo como esto. Mi preferencia -personal es la integridad referencial de la base de datos. La administración de la integridad de la aplicación debería, en mi opinión, limitarse a la lógica comercial. La base de datos debe asegurar que los datos siempre es coherente y válido ...


Para responder a su pregunta en realidad ...

La opción que yo usaría es una restricción de comprobación utilizando un usuario definido Función para verificar los valores. Esto funciona en M $ SQL Server ...

CREATE TABLE Test_Table_1 (id INT IDENTITY(1,1), val INT) 
GO 
CREATE TABLE Test_Table_2 (id INT IDENTITY(1,1), val INT) 
GO 
CREATE TABLE Test_Table_3 (fk_id INT, table_name VARCHAR(64)) 
GO 

CREATE FUNCTION id_exists (@id INT, @table_name VARCHAR(64)) 
RETURNS INT 
AS 
BEGIN 
    IF (@table_name = 'Test_Table_1') 
     IF EXISTS(SELECT * FROM Test_Table_1 WHERE id = @id) 
      RETURN 1 
    ELSE 
    IF (@table_name = 'Test_Table_2') 
     IF EXISTS(SELECT * FROM Test_Table_2 WHERE id = @id) 
      RETURN 1 

    RETURN 0 
END 
GO 

ALTER TABLE Test_Table_3 WITH CHECK ADD CONSTRAINT 
    CK_Test_Table_3 CHECK ((dbo.id_exists(fk_id,table_name)=(1))) 
GO 
ALTER TABLE [dbo].[Test_Table_3] CHECK CONSTRAINT [CK_Test_Table_3] 
GO 

INSERT INTO Test_Table_1 SELECT 1 
GO 
INSERT INTO Test_Table_1 SELECT 2 
GO 
INSERT INTO Test_Table_1 SELECT 3 
GO 
INSERT INTO Test_Table_2 SELECT 1 
GO 
INSERT INTO Test_Table_2 SELECT 2 
GO 
INSERT INTO Test_Table_3 SELECT 3, 'Test_Table_1' 
GO 
INSERT INTO Test_Table_3 SELECT 3, 'Test_Table_2' 
GO 

En ese ejemplo, la instrucción de inserción final fallaría.

1

Puede obtener la integridad referencial FK, al costo de tener una columna en la tabla de notas para cada otra tabla.

create table Notes (
    id int PRIMARY KEY, 
    note varchar (whatever), 
    customer_id int NULL REFERENCES Customer (id), 
    product_id int NULL REFERENCES Product (id) 
) 

Luego necesitará una restricción para asegurarse de tener solo una de las columnas establecidas.

O tal vez no, tal vez podría querer una nota para poder asociar tanto a un cliente como a un producto. Depende de usted.

Este diseño requeriría agregar una nueva columna a Notes si desea agregar otra tabla de referencia.

+0

Esa es probablemente la solución más elegante hasta ahora. – Thilo

Cuestiones relacionadas