database - soporta - relacionar tablas en sql server por codigo
¿Cuál es la mejor manera de manejar las relaciones uno a uno en SQL? (9)
Crearía una relación de supertipo / subtipo.
THINGS
------
PK ThingId
ALPHAS
------
FK ThingId (not null, identifying, exported from THINGS)
AlphaCol1
AlphaCol2
AlphaCol3
BRAVOS
------
FK ThingId (not null, identifying, exported from THINGS)
BravoCol1
BravoCol2
BravoCol3
CHARLIES
--------
FK ThingId (not null, identifying, exported from THINGS)
CharlieCol1
CharlieCol2
CharlieCol3
Entonces, por ejemplo, un alfa que tiene un charlie pero no un bravo: -
insert into things values (1);
insert into alphas values (1,''alpha col 1'',5,''blue'');
insert into charlies values (1,''charlie col 1'',17,''Y'');
Tenga en cuenta que no puede crear más de un charlie para el alfa, como si tratara de crear dos charlies con un ThingId de 1, el segundo inserto obtendría una violación exclusiva de índice / restricción.
Digamos que tengo cosas Alpha que pueden ser o no estar relacionadas con cosas de Bravo o Charlie.
Estas son relaciones uno-a-uno: Ningún Alfa se relacionará con más de un Bravo. Y ningún Bravo se relacionará con más de un Alfa.
Tengo algunos objetivos:
- un sistema que es fácil de aprender y mantener
- la integridad de los datos se aplica en mi base de datos.
- un esquema que coincida con la organización lógica del mundo real de mis datos.
- clases / objetos dentro de mi programación que se mapean bien con las tablas de la base de datos (à la Linq to SQL)
- operaciones rápidas de lectura y escritura
- uso efectivo del espacio (pocos campos nulos)
Tengo tres ideas ...
PK = primary key
FK = foreign key
NU = nullable
Una tabla con muchos campos nullalbe (archivo plano) ...
Alphas
--------
PK AlphaId
AlphaOne
AlphaTwo
AlphaThree
NU BravoOne
NU BravoTwo
NU BravoThree
NU CharlieOne
NU CharlieTwo
NU CharlieThree
Muchas tablas con cero campos nullalbe ...
Alphas
--------
PK AlphaId
AlphaOne
AlphaTwo
AlphaThree
Bravos
--------
FK PK AlphaId
BravoOne
BravoTwo
BravoThree
Charlies
--------
FK PK AlphaId
CharlieOne
CharlieTwo
CharlieThree
Lo mejor (o peor) de ambos: muchas claves externas nullalbe para muchas tablas ...
Alphas
--------
PK AlphaId
AlphaOne
AlphaTwo
AlphaThree
NU FK BravoId
NU FK CharlieId
Bravos
--------
PK BravoId
BravoOne
BravoTwo
BravoThree
Charlies
--------
PK CharlieId
CharlieOne
CharlieTwo
CharlieThree
¿Qué pasa si un Alpha debe ser Bravo o Charlie, pero no ambos?
¿Qué pasa si en lugar de solo Bravos y Charlies, Alphas también pudiera ser cualquiera de Deltas, Echos, Foxtrots o Golfs, etc.?
EDITAR: Esta es una parte de la pregunta: ¿Cuál es el mejor esquema de base de datos para mi navegación?
Me gustaría ir con la opción 1 a menos que tuviera una razón importante para no hacerlo. Puede que no le cueste tanto espacio como cree, especialmente. si está usando varchar en Bravo. No olvide que dividirlo le costará claves extranjeras, identidad secundaria e índices necesarios.
Un lugar donde puede tener problemas es si es poco probable que se necesite Bravo (<% 10) Y necesita consultar rápidamente por uno de sus campos para que lo indexe.
Personalmente, he tenido mucho éxito con su segundo modelo, usando un PK / FK en una sola columna.
Nunca he tenido una situación en la que se requiera que todos los Alphas tengan un registro en una mesa de Bravo o Charlie. Siempre he tratado con 1 <-> 0..1, nunca 1 <-> 1.
En cuanto a su última pregunta, esas son muchas más tablas.
Plantea muchas preguntas que dificultan seleccionar cualquiera de las soluciones propuestas sin mucha más aclaración sobre el problema exacto que está tratando de resolver. Considere no solo mis preguntas de aclaración, sino los criterios que usará para evaluar mis preguntas, como una indicación de la cantidad de detalles requeridos para resolver su problema:
- un sistema que es fácil de aprender y mantener
¿Qué "Sistema" será fácil de aprender y mantener? ¿El código fuente de su aplicación o los datos de la aplicación a través de su interfaz de usuario final?
- la integridad de los datos se aplica en mi base de datos.
¿Qué quiere decir con "forzado dentro de mi base de datos"? ¿Esto significa que de ninguna manera puede controlar la integridad de los datos de otra manera, es decir, el proyecto solo requiere reglas de integridad de datos basadas en DB?
- un esquema que coincida con la organización lógica del mundo real de mis datos.
¿Puede proporcionarnos la organización lógica del mundo real a la que se refiere? Es imposible deducirlo de los tres ejemplos de los datos que intenta almacenar; es decir, suponga que las tres estructuras están completamente equivocadas. ¿Cómo lo sabríamos a menos que conozcamos la especificación del mundo real?
- clases / objetos dentro de mi programación que se mapean bien con las tablas de la base de datos (à la Linq to SQL)
Este requisito parece que tu mano está siendo forzada a crear esto con linq a SQL, ¿es así?
- operaciones rápidas de lectura y escritura
¿Qué es "rápido"? .03 segundos? ¿3 segundos? ¿30 minutos? No está claro porque no especifica el tamaño de los datos y el tipo de operaciones a las que se refiere.
- uso efectivo del espacio (pocos campos nulos)
El uso efectivo del espacio no tiene nada que ver con la cantidad de campos nulos. Si se refiere a una estructura de base de datos normalizada, eso dependerá nuevamente de las especificaciones del mundo real y otros elementos de diseño de la aplicación que no se hayan proporcionado en la pregunta.
Podría tener una tabla de unión que especifique un Alfa y una ID relacionada. A continuación, puede agregar otra columna que especifique si se trata de una identificación para Bravo, Charlie o lo que sea. Mantiene la columna hacia abajo en Alpha, pero agrega algo de complejidad para unir consultas.
Si quiere que cada Alfa esté relacionado con un solo Bravo, votaría por la posibilidad de usar un FK / PK combinado:
Bravos
--------
FK PK AlphaId
BravoOne
BravoTwo
BravoThree
De esta forma, uno y solo un Bravo puede referirse a tus Alfas.
Si los Bravos y Charlies tienen que ser mutuamente excluyentes, el método más simple sería probablemente crear un campo discriminador:
Alpha
--------
PK AlphaId
PK AlphaType NOT NULL IN ("Bravo", "Charlie")
AlphaOne
AlphaTwo
AlphaThree
Bravos
--------
FK PK AlphaId
FK PK AlphaType == "Bravo"
BravoOne
BravoTwo
BravoThree
Charlies
--------
FK PK AlphaId
FK PK AlphaType == "Charlie"
CharlieOne
CharlieTwo
CharlieThree
De esta forma, el campo AlphaType obliga a que los registros siempre pertenezcan exactamente a un subtipo.
Supongo que usará SQL Server 2000 / 2005. Tengo un patrón estándar para las relaciones de 1 a 1 que utilizo, que no es muy diferente a su 2da idea, pero aquí están las diferencias:
Cada entidad debe tener su propia clave primaria primero, por lo que sus tablas Bravo, Charlie, etc. deben definir su propia clave sustituta, además de la columna de clave externa para la tabla Alfa. Está haciendo que su modelo de dominio sea bastante inflexible al especificar que la clave principal de una tabla debe ser exactamente la misma que la clave principal de otra tabla. Por lo tanto, las entidades se acoplan muy estrechamente, y una entidad no puede existir sin otra, que no es una regla comercial que debe aplicarse dentro del diseño de la base de datos.
Agregue una restricción de clave externa entre las columnas AlphaID en las tablas Bravo y Charlie a la columna de clave principal en la tabla Alpha. Esto le da 1-a-muchos, y también le permite especificar si la relación es obligatoria simplemente estableciendo la nulabilidad de la columna FK (algo que no es posible en su diseño actual).
Agregue una restricción de clave única a las tablas Bravo, Charlie, etc. en la columna AlphaID. Esto crea una relación de 1 a 1, con el beneficio adicional de que la clave única también actúa como un índice que puede ayudar a acelerar las consultas que recuperan filas en función del valor de la clave externa.
El mayor beneficio de este enfoque es que el cambio es más fácil:
- ¿Quieres 1 a muchos de vuelta? Suelta la clave única relevante, o simplemente cámbiala a un índice normal
- ¿Quieres que Bravo exista independientemente de Alpha? Ya tiene la clave sustituta, todo lo que hace es configurar la columna AlphaID FK para permitir valores NULL
Tengo un ejemplo que funciona bastante bien hasta ahora, que se ajusta a su modelo:
Tengo Charlie y Bravo Tables con la clave externa alpha_id de Alpha. Como su primer ejemplo, excepto que alfa no es la clave principal, son bravo_id y charlie_id.
Utilizo alpha_id en cada tabla que necesito dirigir a esas entidades, así que, para evitar un SQL que puede causar cierto retraso investigando tanto a Bravo como a Charlie para encontrar cuál es el Alfa, creé una tabla AlphaType y en la tabla Alpha tengo su identificación (alpha_type_id) como clave externa. De esa forma puedo saber de manera programática qué tipo de AlphaType estoy tratando sin unirme a tablas que pueden tener tropecientos de registros. en tSQL:
// For example sake lets think Id as a CHAR.
// and pardon me on any mistake, I dont have the exact code here,
// but you can get the idea
SELECT
(CASE alpha_type_id
WHEN ''B'' THEN ''[Bravo].[Name]''
WHEN ''C'' THEN ''[Charlie].[Name]''
ELSE Null
END)
FROM ...
Un enfoque más es tener 3 tablas para almacenar las 3 entidades y tener una tabla separada para almacenar las relaciones.